Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cfaa0ca470 | |||
| c609be40f8 |
@@ -145,7 +145,63 @@ Un ejercicio puede combinar conceptos de niveles anteriores, pero **no debe exig
|
||||
|
||||
---
|
||||
|
||||
## 7. Lo que está prohibido
|
||||
## 7. Estilo didáctico al explicar conceptos ("para tontos")
|
||||
|
||||
Los capítulos no solo enuncian ejercicios: también **explican** los conceptos que el lector necesita.
|
||||
Esa explicación sigue un estilo llano, concreto y progresivo —el mismo que se usó en
|
||||
`book/14-entrada-salida-estandar.md`—, pensado para que el lector **entienda de verdad** y no solo
|
||||
lea. Estas reglas aplican a **todo capítulo** que explique conceptos.
|
||||
|
||||
**Analogía cotidiana primero.** Todo concepto arranca con una comparación del mundo real que el lector
|
||||
ya domina; recién después aparece el término técnico. Ejemplos del capítulo 14: las tres tuberías
|
||||
(`stdin`/`stdout`/`stderr`) son "una fábrica"; `getchar` es "sacar caramelos de a uno"; el búfer es
|
||||
"el villano de la película". La analogía se sostiene durante toda la explicación; no se abandona a la
|
||||
primera frase.
|
||||
|
||||
**Títulos con gancho, no etiquetas.** En vez de "Introducción a `getchar`", el título promete algo
|
||||
concreto: "`getchar`: el caramelito de a uno". Lo mismo vale para las subsecciones.
|
||||
|
||||
**Explicar el POR QUÉ, no solo el qué.** Cada regla llega con su motivo. No alcanza con decir "guardá
|
||||
en `int`, no en `char`": hay que explicar por qué (tiene que representar los 256 bytes posibles **y**
|
||||
un valor extra, `EOF`).
|
||||
|
||||
**Voz cercana y frases cortas.** Se trata al lector de "vos" (ver sección 6). Párrafos breves, en
|
||||
presente, sin rodeos. Se permite —y se espera— marcar la idea clave con **negrita** y con MAYÚSCULAS
|
||||
ocasionales.
|
||||
|
||||
**Cómo estructurar un capítulo largo:**
|
||||
|
||||
- Dividirlo en **partes** con un **índice** al inicio. La tabla lleva, por cada parte, "la idea en una
|
||||
frase".
|
||||
- Después de cada concepto, un **bloque de práctica** con uno o más ejercicios cortos, antes de
|
||||
avanzar al siguiente concepto.
|
||||
- Cerrar con un apartado tipo "lo que te llevás": las ideas clave en pocos bullets, y el puente al
|
||||
capítulo siguiente.
|
||||
|
||||
**Recursos que se repiten:**
|
||||
|
||||
- **Apodos para las trampas** clásicas: "la trampa N.º 1", "el bug más famoso del principiante", "el
|
||||
villano de la película".
|
||||
- **Blockquotes** (`>`) para notas, advertencias y "momentos ajá": "Momento ajá", "Ojo con esto",
|
||||
"Para guardar", "Truco de laboratorio". En el PDF todas se dibujan con fondo de color (sección 10).
|
||||
- **Tablas comparativas** para contrastar opciones o señales parecidas (p. ej. `EOF` vs `'\0'` vs
|
||||
`'\n'`).
|
||||
- **Diagramas ASCII** para mostrar lo visual: flujos conectados, los dos búferes en serie.
|
||||
- **Código ilustrativo comentado en lenguaje llano**: cada línea que introduce algo nuevo lleva un
|
||||
comentario claro y **de varias líneas** que dice exactamente qué hace. Los bloques declaran su
|
||||
lenguaje en el fence para que `highlight.js` los resalte (sección 10).
|
||||
- **Escenario de prueba** en cada ejercicio: un bloque `text` con la entrada y la salida esperada,
|
||||
para que el lector pueda **comprobar** su solución.
|
||||
|
||||
**El límite que NO se cruza.** Este estilo permite **código ilustrativo para explicar un concepto**
|
||||
(una llamada a una función, un esqueleto mínimo, un patrón genérico), pero **nunca** la solución de un
|
||||
ejercicio. Las reglas no negociables (sección 2) siguen mandando: se entrega el **problema**; la
|
||||
lógica que resuelve la consigna la escribe el lector. El código de ejemplo sirve para **entender** una
|
||||
herramienta, jamás para resolver un enunciado del libro.
|
||||
|
||||
---
|
||||
|
||||
## 8. Lo que está prohibido
|
||||
|
||||
- Escribir la solución, total o parcial, del enunciado (incluida la lógica en pseudocódigo).
|
||||
- Convertir el ejercicio en un proyecto grande, con build system, múltiples archivos o dependencias externas.
|
||||
@@ -156,7 +212,7 @@ Un ejercicio puede combinar conceptos de niveles anteriores, pero **no debe exig
|
||||
|
||||
---
|
||||
|
||||
## 8. Flujo para agregar contenido
|
||||
## 9. Flujo para agregar contenido
|
||||
|
||||
Checklist al crear o editar un ejercicio:
|
||||
|
||||
@@ -175,7 +231,7 @@ Checklist al crear o editar un ejercicio:
|
||||
|
||||
---
|
||||
|
||||
## 9. Generación de PDF (`dist/`)
|
||||
## 10. Generación de PDF (`dist/`)
|
||||
|
||||
Cada capítulo trabajado se publica como **PDF** en `dist/`, con el **mismo nombre** que su
|
||||
Markdown: `book/12-arenas.md` → `dist/12-arenas.pdf`.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,9 @@
|
||||
# Capítulo 13 — Entrada y salida estándar (sin archivos)
|
||||
# Capítulo 14 — Entrada y salida estándar (sin archivos)
|
||||
|
||||
> Capítulo intermedio, pero **escrito para que se entienda de verdad**. Se apoya en variables (`02`),
|
||||
> operadores (`03`), `if` y bucles (`04`), funciones (`05`) y arreglos y cadenas (`06`).
|
||||
>
|
||||
> Es el **puente** hacia el capítulo de archivos (`14-archivos`). Todo lo que aprendas acá sobre
|
||||
> Es el **puente** hacia el capítulo de archivos (`15-archivos`). Todo lo que aprendas acá sobre
|
||||
> `stdin`, búferes y `EOF` lo vas a reusar tal cual para leer archivos. La única diferencia será que,
|
||||
> en vez de leer del teclado, vas a leer de un archivo.
|
||||
|
||||
@@ -30,7 +30,7 @@ del capítulo.
|
||||
| **7** | Robustez | Que tu programa no se rompa nunca. |
|
||||
| **8** | Proyecto final | Construís tu propia consola de comandos. |
|
||||
|
||||
Los **ejercicios** se numeran en orden: `13.1`, `13.2`, `13.3`, y así. Cada uno trae su **escenario de
|
||||
Los **ejercicios** se numeran en orden: `14.1`, `14.2`, `14.3`, y así. Cada uno trae su **escenario de
|
||||
prueba** (qué entra y qué tiene que salir) para que puedas **comprobar** tu solución.
|
||||
|
||||
> **Regla de oro del libro:** el capítulo explica y muestra **cómo funciona** cada cosa, pero **los
|
||||
@@ -243,7 +243,7 @@ diferencia:
|
||||
|
||||
## Práctica de la Parte 1
|
||||
|
||||
### Ejercicio 13.1 — Separar la salida útil de los avisos
|
||||
### Ejercicio 14.1 — Separar la salida útil de los avisos
|
||||
|
||||
**Conceptos** · `stdout`, `stderr`, `fprintf`, redirección de salidas
|
||||
|
||||
@@ -278,14 +278,14 @@ Aviso: 3 registros tenían fecha inválida.
|
||||
- [ ] Al correr con `>` y `2>`, cada mensaje cae en su archivo y ninguno aparece en el otro.
|
||||
- [ ] Usa `fprintf` indicando el flujo (`stdout`/`stderr`) en cada escritura.
|
||||
|
||||
### Ejercicio 13.2 — Detective de flujos
|
||||
### Ejercicio 14.2 — Detective de flujos
|
||||
|
||||
**Conceptos** · `stdout`, `stderr`, redirección (`>`, `2>`, `2>&1`), tuberías
|
||||
|
||||
**Contexto** · Antes de creer que entendiste los flujos, hay que **verlos**. Vas a conectar el mismo
|
||||
programa de varias maneras y comparar qué termina dónde.
|
||||
|
||||
**Consigna** · Tomá el programa de 13.1 (o escribí uno mínimo que mande una línea a `stdout` y otra a
|
||||
**Consigna** · Tomá el programa de 14.1 (o escribí uno mínimo que mande una línea a `stdout` y otra a
|
||||
`stderr`) y corrélo de estas formas, anotando para cada una **qué queda en pantalla** y **qué en cada
|
||||
archivo**:
|
||||
|
||||
@@ -462,7 +462,7 @@ int fgetc(FILE *stream); /* igual que getc, pero siempre es función */
|
||||
|
||||
## Práctica de la Parte 2
|
||||
|
||||
### Ejercicio 13.3 — Contador de caracteres seguro
|
||||
### Ejercicio 14.3 — Contador de caracteres seguro
|
||||
|
||||
**Conceptos** · `getchar`, `int` vs `char`, `EOF`, bytes altos (`0xFF`)
|
||||
|
||||
@@ -496,7 +496,7 @@ Caracteres leídos: 3
|
||||
- [ ] Termina limpio en `EOF`, sin bucle infinito.
|
||||
- [ ] El resultado coincide con el tamaño real de la entrada.
|
||||
|
||||
### Ejercicio 13.4 — ¿Cuántos saltos de línea hay?
|
||||
### Ejercicio 14.4 — ¿Cuántos saltos de línea hay?
|
||||
|
||||
**Conceptos** · `getchar`, comparación de bytes, `'\n'`, `EOF`
|
||||
|
||||
@@ -617,7 +617,7 @@ limpiar los residuos que deja `scanf`. Guardátelo.
|
||||
|
||||
## Práctica de la Parte 3
|
||||
|
||||
### Ejercicio 13.5 — Protección contra desbordamiento
|
||||
### Ejercicio 14.5 — Protección contra desbordamiento
|
||||
|
||||
**Conceptos** · `fgets` con búfer fijo, truncamiento, detección de líneas largas, descarte del resto
|
||||
|
||||
@@ -650,7 +650,7 @@ Aviso: la línea era más larga que el búfer (20 bytes) y fue recortada.
|
||||
- [ ] El resto de la línea se descarta; no contamina la lectura siguiente.
|
||||
- [ ] No hay desbordamiento ni comportamiento indefinido.
|
||||
|
||||
### Ejercicio 13.6 — Contador de palabras
|
||||
### Ejercicio 14.6 — Contador de palabras
|
||||
|
||||
**Conceptos** · `fgets`, recorrido de una cadena, espacios, bucles
|
||||
|
||||
@@ -783,7 +783,7 @@ limpiar es el bucle de 4.5.
|
||||
|
||||
## Práctica de la Parte 4
|
||||
|
||||
### Ejercicio 13.7 — Corrección de búfer tras `scanf`
|
||||
### Ejercicio 14.7 — Corrección de búfer tras `scanf`
|
||||
|
||||
**Conceptos** · `scanf`, `fgets`, `\n` pendiente, limpieza del búfer
|
||||
|
||||
@@ -816,7 +816,7 @@ Nombre: Ana
|
||||
- [ ] `fgets` obtiene el nombre, **no** una línea vacía.
|
||||
- [ ] Muestra número y nombre correctos.
|
||||
|
||||
### Ejercicio 13.8 — Cuestionario de datos mixtos
|
||||
### Ejercicio 14.8 — Cuestionario de datos mixtos
|
||||
|
||||
**Conceptos** · `scanf`, `getchar`, `fgets`, saltear blancos, orden de lectura, residuos
|
||||
|
||||
@@ -854,7 +854,7 @@ Nombre: Juan Gómez
|
||||
- [ ] No quedan residuos: la lectura del nombre **no** está "corrida".
|
||||
- [ ] Comprueba los valores de retorno.
|
||||
|
||||
### Ejercicio 13.9 — Menú de opciones de longitud fija
|
||||
### Ejercicio 14.9 — Menú de opciones de longitud fija
|
||||
|
||||
**Conceptos** · `getchar`, consumir el resto de la línea, bucles, validación
|
||||
|
||||
@@ -1022,7 +1022,7 @@ int main(void) {
|
||||
|
||||
## Práctica de la Parte 5
|
||||
|
||||
### Ejercicio 13.10 — Validador de edad numérica
|
||||
### Ejercicio 14.10 — Validador de edad numérica
|
||||
|
||||
**Conceptos** · `scanf`, valor de retorno, fallo de conversión, descarte de entrada inválida
|
||||
|
||||
@@ -1052,7 +1052,7 @@ Salida: Entrada inválida: se esperaba un número entero.
|
||||
- [ ] Con un número válido, lo muestra correctamente.
|
||||
- [ ] No deja la entrada "sucia" para una lectura posterior.
|
||||
|
||||
### Ejercicio 13.11 — Extracción de tokens con formato avanzado
|
||||
### Ejercicio 14.11 — Extracción de tokens con formato avanzado
|
||||
|
||||
**Conceptos** · `scanf` con ancho máximo (`%19s`), supresión (`*`), valor de retorno
|
||||
|
||||
@@ -1082,7 +1082,7 @@ Salida: valor = 42
|
||||
- [ ] Extrae el número correctamente en ambos escenarios.
|
||||
- [ ] Comprueba el retorno de `scanf` (`== 1`).
|
||||
|
||||
### Ejercicio 13.12 — La calculadora de una línea
|
||||
### Ejercicio 14.12 — La calculadora de una línea
|
||||
|
||||
**Conceptos** · `scanf` con formato mixto (`%d %c %d`), valor de retorno
|
||||
|
||||
@@ -1175,13 +1175,13 @@ Reglas prácticas:
|
||||
2. **Cuando examinés bytes crudos, usá `unsigned char`.** Comparar `0xC3` contra un `char` con signo
|
||||
trae resultados confusos.
|
||||
3. **Un `char` no alcanza para todo símbolo.** Para eso existen `wchar_t` y `char32_t` (capítulo
|
||||
`15-tipos-stddef`).
|
||||
`16-tipos-stddef`).
|
||||
4. **No adivines la codificación.** Si los acentos salen "raros", casi siempre es que la codificación
|
||||
del texto no coincide con la que espera la terminal.
|
||||
|
||||
## Práctica de la Parte 6
|
||||
|
||||
### Ejercicio 13.13 — Filtro de terminadores de línea
|
||||
### Ejercicio 14.13 — Filtro de terminadores de línea
|
||||
|
||||
**Conceptos** · `getchar`, `EOF`, `'\n'`, `'\r'`, `'\0'`, distinción de símbolos
|
||||
|
||||
@@ -1222,7 +1222,7 @@ d
|
||||
- [ ] Detecta `'\0'` como byte real `0x00` (no lo confunde con `EOF`).
|
||||
- [ ] Termina en el primer `EOF`, con la etiqueta `<EOF>` incluida.
|
||||
|
||||
### Ejercicio 13.14 — Radiografía de un acento
|
||||
### Ejercicio 14.14 — Radiografía de un acento
|
||||
|
||||
**Conceptos** · `getchar`, bytes altos, UTF-8 multibyte, `unsigned char`
|
||||
|
||||
@@ -1359,7 +1359,7 @@ entrada es válida. `strtod` funciona igual, pero para `double`.
|
||||
|
||||
## Práctica de la Parte 7
|
||||
|
||||
### Ejercicio 13.15 — Bucle robusto ante cierre de terminal
|
||||
### Ejercicio 14.15 — Bucle robusto ante cierre de terminal
|
||||
|
||||
**Conceptos** · `getchar`, `EOF`, corte de bucles, fin de entrada por teclado
|
||||
|
||||
@@ -1394,7 +1394,7 @@ Fin de la entrada (EOF). Chau.
|
||||
- [ ] Con la entrada del ejemplo, informa **11** caracteres y **2** líneas.
|
||||
- [ ] Muestra un mensaje de cierre y termina.
|
||||
|
||||
### Ejercicio 13.16 — Validador de número a prueba de balas
|
||||
### Ejercicio 14.16 — Validador de número a prueba de balas
|
||||
|
||||
**Conceptos** · `fgets`, `strtol`, validación de rango, detección de basura
|
||||
|
||||
@@ -1455,7 +1455,7 @@ leer líneas acotadas, interpretar el comando, validar números, manejar residuo
|
||||
|
||||
## Ejercicio final
|
||||
|
||||
### Ejercicio 13.17 — (JEFE) Simulador de consola de comandos interactiva
|
||||
### Ejercicio 14.17 — (JEFE) Simulador de consola de comandos interactiva
|
||||
|
||||
**Conceptos** · `fgets`, `sscanf`, `stdin`/`stdout`/`stderr`, limpieza de búfer, validación numérica,
|
||||
`EOF`, corte de bucles, comandos con formato.
|
||||
@@ -1550,7 +1550,7 @@ tubería con búfer**. Todo lo demás se deduce de ahí.
|
||||
`EOF`.
|
||||
- **Un carácter no siempre es un byte**: una `á` son dos bytes.
|
||||
|
||||
Y el puente hacia lo que viene: **para C, un archivo es un flujo más**. En `14-archivos` vas a reusar
|
||||
Y el puente hacia lo que viene: **para C, un archivo es un flujo más**. En `15-archivos` vas a reusar
|
||||
**exactamente** estas ideas —`fgetc`, `fgets`, `fscanf`, `feof`, los búferes, `EOF`— solo que sobre un
|
||||
flujo abierto con `fopen` en lugar de sobre `stdin`. Si dominaste este capítulo, el de archivos es
|
||||
casi el mismo capítulo con una apertura y un cierre.
|
||||
@@ -1,12 +1,12 @@
|
||||
# Capítulo 14 — Archivos
|
||||
# Capítulo 15 — Archivos
|
||||
|
||||
> Capítulo intermedio/avanzado. Se apoya en lo aprendido sobre arreglos (`06`), punteros (`07`),
|
||||
> `struct` (`08`), memoria dinámica (`09-memoria-dinamica`), entrada/salida estándar
|
||||
> (`13-entrada-salida-estandar`) y arenas (`12-arenas`).
|
||||
> (`14-entrada-salida-estandar`) y arenas (`12-arenas`).
|
||||
> Se recomienda leerlo después de tener claros `malloc`, `free`, el uso de punteros,
|
||||
> el manejo de `stdin`/`stdout`/`stderr` y la idea de reservar memoria en bloques (arenas).
|
||||
|
||||
## 14.1 ¿Por qué leer y escribir archivos?
|
||||
## 15.1 ¿Por qué leer y escribir archivos?
|
||||
|
||||
Hasta ahora, nuestros programas intercambiaban información únicamente a través de la consola
|
||||
(entrada por teclado y salida por pantalla). Esto está bien para ejercicios cortos, pero
|
||||
@@ -17,7 +17,7 @@ archivos compactados.
|
||||
Un archivo nos permite guardar información en disco para usarla más tarde, compartirla entre
|
||||
programas o procesarla por lotes. El desafío es hacerlo de forma **clara, segura y correcta**.
|
||||
|
||||
### 14.1.1 Texto vs Binario
|
||||
### 15.1.1 Texto vs Binario
|
||||
|
||||
En C, los archivos se dividen en dos grandes categorías:
|
||||
|
||||
@@ -32,7 +32,7 @@ binario como si fuera texto corrompe su estructura. Por eso, al abrir un archivo
|
||||
usamos modos distintos: `r`, `w`, `a` para texto y `rb`, `wb`, `ab` (más `+` cuando corresponde)
|
||||
para binario.
|
||||
|
||||
### 14.1.2 Recursos: abrir y cerrar
|
||||
### 15.1.2 Recursos: abrir y cerrar
|
||||
|
||||
Todo archivo abierto consume un recurso del sistema. Por eso, **siempre hay que cerrarlo**
|
||||
cuando terminamos de usarlo. El par básico es:
|
||||
@@ -47,13 +47,13 @@ Un error común es olvidar `fclose()` o no cerrarlo en todos los caminos posible
|
||||
si ocurre un error a mitad del proceso). Más adelante veremos cómo mitigar esto usando
|
||||
distintas estrategias de gestión de memoria/buffers.
|
||||
|
||||
## 14.2 Lectura y escritura de archivos de texto
|
||||
## 15.2 Lectura y escritura de archivos de texto
|
||||
|
||||
La librería estándar de C (`stdio.h`) ofrece un conjunto de funciones para trabajar con archivos.
|
||||
Antes de usarlas, veamos **cada una**: cómo se llama, qué recibe y qué devuelve. Casi todas giran
|
||||
en torno al tipo `FILE *`, que es el **manejador** (handle) del archivo abierto.
|
||||
|
||||
### 14.2.1 Modos de apertura
|
||||
### 15.2.1 Modos de apertura
|
||||
|
||||
`fopen` recibe la ruta y un **modo** que decide qué se puede hacer con el archivo:
|
||||
|
||||
@@ -79,16 +79,16 @@ Agregando una `b` (`"rb"`, `"wb"`, `"ab"`, ...) se abre en **modo binario**.
|
||||
>
|
||||
> Esa es toda la diferencia (y solo importa en Windows; en Linux/macOS no hay traducción). Por eso los
|
||||
> archivos cuyos bytes deben leerse **exactos** —imágenes, audio, o la cabecera ASCII de un PPM
|
||||
> mezclada con píxeles— se abren con `"b"`. Ojo: el `\n` de la cabecera PPM del ejemplo (14.5) es un
|
||||
> mezclada con píxeles— se abren con `"b"`. Ojo: el `\n` de la cabecera PPM del ejemplo (15.5) es un
|
||||
> **byte real del archivo** (`0x0A`), no una traducción del modo texto.
|
||||
|
||||
### 14.2.2 Referencia: funciones de texto
|
||||
### 15.2.2 Referencia: funciones de texto
|
||||
|
||||
#### `fopen` — abrir un archivo
|
||||
```c
|
||||
FILE *fopen(const char *path, const char *mode);
|
||||
```
|
||||
- **Recibe:** `path`, la ruta del archivo; `mode`, el modo de apertura (ver 14.2.1).
|
||||
- **Recibe:** `path`, la ruta del archivo; `mode`, el modo de apertura (ver 15.2.1).
|
||||
- **Devuelve:** un `FILE *` (el manejador del archivo abierto) o `NULL` si no se pudo abrir.
|
||||
- **Ojo:** hay que verificar siempre `NULL` antes de usar el manejador.
|
||||
|
||||
@@ -191,7 +191,7 @@ Y leído paso a paso:
|
||||
> Fijate en el gráfico: el cursor termina en la posición 9, **justo antes del `\n`**. `fscanf` consume
|
||||
> todos los dígitos de cada número, pero **nunca** el `\n` que sigue al último: ese separador queda
|
||||
> **sin leer**. Si tu programa necesita leer lo que viene inmediatamente después, tenés que "comerte"
|
||||
> ese separador con `fgetc()`. Es exactamente lo que hace el ejemplo de la sección 14.5.2 antes de leer
|
||||
> ese separador con `fgetc()`. Es exactamente lo que hace el ejemplo de la sección 15.5.2 antes de leer
|
||||
> los píxeles.
|
||||
|
||||
#### `feof` — ¿se llegó al final?
|
||||
@@ -230,7 +230,7 @@ int tolower(int c);
|
||||
> `printf`, `scanf`, `malloc`, `free` y `sizeof` ya se vieron en capítulos anteriores; acá nos
|
||||
> concentramos en lo específico de archivos.
|
||||
|
||||
### 14.2.3 Ejemplo: leer un archivo carácter por carácter
|
||||
### 15.2.3 Ejemplo: leer un archivo carácter por carácter
|
||||
|
||||
Con `fgetc()` leés **un byte por vez**. El valor de retorno es un `int`, no un `char`, para que
|
||||
pueda distinguirse el valor `EOF` (fin de archivo, normalmente `-1`). Este es el patrón clásico
|
||||
@@ -266,7 +266,7 @@ Observá tres detalles que se repiten en **todos** los programas con archivos:
|
||||
2. El bucle corta cuando `fgetc()` devuelve `EOF`.
|
||||
3. Se cierran **los dos** archivos, en orden inverso al que se abrieron.
|
||||
|
||||
### 14.2.4 Ejemplo: leer línea por línea con `fgets`
|
||||
### 15.2.4 Ejemplo: leer línea por línea con `fgets`
|
||||
|
||||
Para trabajar línea a línea, `fgets()` es más cómodo que `fgetc()`. Lee como máximo `n - 1`
|
||||
caracteres, o hasta encontrar un `\n` (que **deja incluido** en el buffer), o hasta el fin del
|
||||
@@ -298,7 +298,7 @@ int main(void) {
|
||||
> buffer, `fgets()` la entrega **cortada** en varios pedazos. Para este capítulo, asumimos líneas
|
||||
> razonables.
|
||||
|
||||
### 14.2.5 Ejemplo: escribir con formato (`fprintf`)
|
||||
### 15.2.5 Ejemplo: escribir con formato (`fprintf`)
|
||||
|
||||
`fprintf()` es a un archivo lo que `printf()` es a la pantalla: acepta el mismo formato.
|
||||
|
||||
@@ -325,15 +325,15 @@ int main(void) {
|
||||
Con modo `"w"` el archivo se **trunca** (si ya existía, se borra su contenido). Para **agregar**
|
||||
al final sin borrar lo anterior, se usa el modo `"a"`.
|
||||
|
||||
## 14.3 Ejercicios: archivos de texto
|
||||
## 15.3 Ejercicios: archivos de texto
|
||||
|
||||
> **Regla fundamental:** ningún ejercicio incluye código de solución. Solo se describe el problema,
|
||||
> entrada/salida, conceptos y criterios de aceptación. Se permiten fragmentos de entrada/salida
|
||||
> esperada como ejemplos.
|
||||
|
||||
Estos ejercicios trabajan sobre lo visto en la sección 14.2: `fgetc`, `fgets`, `fprintf` y `feof`.
|
||||
Estos ejercicios trabajan sobre lo visto en la sección 15.2: `fgetc`, `fgets`, `fprintf` y `feof`.
|
||||
|
||||
### Ejercicio 14.1 — Contador de líneas y caracteres (texto, básico)
|
||||
### Ejercicio 15.1 — Contador de líneas y caracteres (texto, básico)
|
||||
|
||||
**Conceptos** · `FILE*`, `fopen`, `fclose`, `fgetc`, `feof`
|
||||
|
||||
@@ -376,7 +376,7 @@ incrementar al encontrar `\n`). Siempre validar que el archivo se abrió correct
|
||||
- [ ] Cierra el archivo con `fclose()` antes de terminar.
|
||||
- [ ] Muestra salida con formato claro.
|
||||
|
||||
### Ejercicio 14.2 — Copia de archivo de texto (texto, básico)
|
||||
### Ejercicio 15.2 — Copia de archivo de texto (texto, básico)
|
||||
|
||||
**Conceptos** · `FILE*`, `fopen`, `fclose`, `fgetc`, `fputc`
|
||||
|
||||
@@ -414,7 +414,7 @@ y escribir con `fputc()`. Verificar aperturas y cierres. No modificar el conteni
|
||||
- [ ] Reporta errores de forma clara.
|
||||
- [ ] Cierra ambos archivos.
|
||||
|
||||
### Ejercicio 14.3 — Leer líneas y guardar filtradas (texto, intermedio)
|
||||
### Ejercicio 15.3 — Leer líneas y guardar filtradas (texto, intermedio)
|
||||
|
||||
**Conceptos** · `fgets`, buffers, cadenas, condicionales
|
||||
|
||||
@@ -464,7 +464,7 @@ Abrir archivos en modo texto.
|
||||
- [ ] Informa cantidad de líneas copiadas.
|
||||
- [ ] Maneja errores de apertura correctamente.
|
||||
|
||||
## 14.4 Lectura y escritura de archivos binarios
|
||||
## 15.4 Lectura y escritura de archivos binarios
|
||||
|
||||
Cuando trabajamos con datos estructurados o con formatos como imágenes, necesitamos leer/escribir
|
||||
**bytes exactos**, sin que el sistema modifique nada (ni convierta finales de línea). Para eso
|
||||
@@ -473,10 +473,10 @@ usamos `fread()` y `fwrite()`, junto con funciones para ubicarse dentro del arch
|
||||
> **Antes de leer, mirá.** Un archivo binario no se puede abrir con un editor de texto: vas a ver
|
||||
> basura, y encima el editor puede corromperlo. Para *ver* los bytes sin instalar nada, usá
|
||||
> **ImHex Web** (<https://web.imhex.werwolv.net/>): un editor hexadecimal que corre entero en el
|
||||
> navegador. Abrí ahí el BMP de la sección 14.8.6 o el PPM de la 14.5.1, ubicá los offsets y
|
||||
> navegador. Abrí ahí el BMP de la sección 15.8.6 o el PPM de la 15.5.1, ubicá los offsets y
|
||||
> contrastá campo por campo lo que muestra la herramienta con lo que escribe tu programa.
|
||||
|
||||
### 14.4.1 Referencia: funciones binarias
|
||||
### 15.4.1 Referencia: funciones binarias
|
||||
|
||||
#### `fread` — leer un bloque
|
||||
```c
|
||||
@@ -531,7 +531,7 @@ dependiendo del formato y de la plataforma. En este capítulo nos enfocamos en *
|
||||
la estructura byte a byte del archivo** y leerlo correctamente según su especificación,
|
||||
sin asumir conversiones mágicas.
|
||||
|
||||
### 14.4.2 Ejemplo: averiguar el tamaño de un archivo
|
||||
### 15.4.2 Ejemplo: averiguar el tamaño de un archivo
|
||||
|
||||
Antes de leer un archivo binario completo conviene saber **cuántos bytes tiene**. El truco es
|
||||
moverse al final con `fseek()`, preguntar la posición con `ftell()` y volver al principio con
|
||||
@@ -561,7 +561,7 @@ int main(void) {
|
||||
> `long` alcanza para archivos de tamaño normal. Para archivos gigantes existen `fseeko()` y
|
||||
> `ftello()` (con `off_t`), pero no hacen falta en este capítulo.
|
||||
|
||||
### 14.4.3 Ejemplo: leer el archivo completo a memoria
|
||||
### 15.4.3 Ejemplo: leer el archivo completo a memoria
|
||||
|
||||
El patrón es: medir el tamaño, reservar un bloque con `malloc()`, leer todo de una sola vez con
|
||||
`fread()` y **siempre** liberar al terminar:
|
||||
@@ -600,7 +600,7 @@ int main(void) {
|
||||
> `fread()` devuelve **cuántos elementos** leyó realmente. Puede leer menos de lo pedido si el
|
||||
> archivo se acorta o si ocurre un error, así que conviene comparar con lo esperado.
|
||||
|
||||
### 14.4.4 Ejemplo: leer una cabecera fija a una `struct`
|
||||
### 15.4.4 Ejemplo: leer una cabecera fija a una `struct`
|
||||
|
||||
Los archivos binarios suelen empezar con una cabecera de tamaño fijo. Se puede leer de una sola
|
||||
vez dentro de una `struct` que tenga **exactamente** el mismo diseño de bytes:
|
||||
@@ -641,14 +641,14 @@ int main(void) {
|
||||
> `struct` en memoria puede **no coincidir** con el del archivo. En esos casos conviene leer los
|
||||
> campos de a uno con `fread()` a variables sueltas, en lugar de a una `struct` entera.
|
||||
|
||||
## 14.5 Ejemplo guiado: otro formato binario — PPM (Netpbm)
|
||||
## 15.5 Ejemplo guiado: otro formato binario — PPM (Netpbm)
|
||||
|
||||
Antes del desafío de BMP, practiquemos con un formato binario **más simple todavía**: el **PPM**
|
||||
(Portable PixMap), uno de los formatos **Netpbm**. Su virtud didáctica es que su cabecera es
|
||||
**texto plano** y sus datos son una **matriz de colores sin compresión ni padding**, así que
|
||||
separa muy bien "leer la cabecera" de "leer los píxeles".
|
||||
|
||||
### 14.5.1 Descripción del formato PPM (variante P6)
|
||||
### 15.5.1 Descripción del formato PPM (variante P6)
|
||||
|
||||
Un archivo `.ppm` binario (variante **P6**) tiene esta estructura:
|
||||
|
||||
@@ -676,7 +676,7 @@ Algunas diferencias con BMP que conviene notar:
|
||||
| Orden de las filas | Arriba → abajo | Abajo → arriba |
|
||||
| Relleno por fila (padding) | No tiene | Múltiplo de 4 bytes |
|
||||
|
||||
### 14.5.2 Cómo leerlo
|
||||
### 15.5.2 Cómo leerlo
|
||||
|
||||
El siguiente programa lee la cabecera con `fscanf()`/`fgetc()` (son texto) y luego los píxeles con
|
||||
`fread()` (son binario). El truco clave está en el **paso 3**: después de `maxval` hay
|
||||
@@ -703,7 +703,7 @@ int main(void) {
|
||||
}
|
||||
|
||||
/* 2. ancho, alto y valor máximo (son números en ASCII).
|
||||
* Detalle de fscanf: ver la sección 14.2.2. */
|
||||
* Detalle de fscanf: ver la sección 15.2.2. */
|
||||
int width, height, maxval;
|
||||
if (fscanf(fp, "%d %d %d", &width, &height, &maxval) != 3) {
|
||||
fprintf(stderr, "cabecera PPM inválida\n");
|
||||
@@ -750,14 +750,14 @@ int main(void) {
|
||||
> mismas que necesitarás para BMP: leer y validar la firma, extraer dimensiones, consumir el
|
||||
> separador exacto entre cabecera y datos, y mapear `(x, y)` a un índice del buffer. La diferencia
|
||||
> es que BMP agrega **orden invertido de filas** y **relleno (padding) por fila**, que veremos en la
|
||||
> sección 14.8.
|
||||
> sección 15.8.
|
||||
|
||||
## 14.6 Gestión de memoria: `malloc/free` vs Arenas
|
||||
## 15.6 Gestión de memoria: `malloc/free` vs Arenas
|
||||
|
||||
Al leer archivos, especialmente archivos binarios de tamaño variable o con estructuras anidadas,
|
||||
necesitamos almacenar lo leído en memoria. Tenemos dos enfoques principales:
|
||||
|
||||
### 14.6.1 Con `malloc` y `free`
|
||||
### 15.6.1 Con `malloc` y `free`
|
||||
|
||||
- Reservamos exactamente lo que necesitamos (`malloc` del tamaño leído).
|
||||
- Liberamos cada bloque cuando ya no lo usamos (`free`).
|
||||
@@ -765,7 +765,7 @@ necesitamos almacenar lo leído en memoria. Tenemos dos enfoques principales:
|
||||
- **Desventaja:** si leemos muchos bloques o estructuras pequeñas, debemos rastrear cada `free`.
|
||||
También complica liberar todo ante un error a mitad del proceso.
|
||||
|
||||
### 14.6.2 Con arenas (bump allocator)
|
||||
### 15.6.2 Con arenas (bump allocator)
|
||||
|
||||
Recordando el concepto del Capítulo 12: reservamos **un bloque grande** una sola vez,
|
||||
avanzamos un cursor para repartir memoria y **liberamos todo junto** (reiniciamos cursor o
|
||||
@@ -783,7 +783,7 @@ Aplicado a lectura de archivos:
|
||||
a **leer archivos correctamente** y que puedas implementar la lectura **usando malloc/free**
|
||||
y también **usando arenas**, entendiendo cuándo conviene cada uno.
|
||||
|
||||
## 14.7 Errores y robustez
|
||||
## 15.7 Errores y robustez
|
||||
|
||||
Al trabajar con archivos, hay que considerar fallas posibles:
|
||||
|
||||
@@ -801,13 +801,13 @@ Al trabajar con archivos, hay que considerar fallas posibles:
|
||||
4. Cerrar el archivo en todos los caminos (incluso ante errores). Esto puede hacerse con cuidado
|
||||
o estructurando el código para asegurar el cierre.
|
||||
|
||||
## 14.8 El formato BMP: documentación de referencia
|
||||
## 15.8 El formato BMP: documentación de referencia
|
||||
|
||||
Antes del desafío final, necesitamos entender el formato que vamos a interpretar: **BMP**
|
||||
(Windows Bitmap). Lo elegimos porque es uno de los formatos de imagen **más simples** de leer:
|
||||
guarda los píxeles **sin compresión** y documenta su estructura con cabeceras bien definidas.
|
||||
|
||||
### 14.8.1 Estructura general de un BMP
|
||||
### 15.8.1 Estructura general de un BMP
|
||||
|
||||
Un archivo `.bmp` se compone de estas partes, en este orden:
|
||||
|
||||
@@ -816,7 +816,7 @@ Un archivo `.bmp` se compone de estas partes, en este orden:
|
||||
3. **Paleta de colores** (opcional): solo para profundidades de 1, 4 u 8 bits.
|
||||
4. **Datos de píxeles** (pixel data): la matriz de píxeles.
|
||||
|
||||
### 14.8.2 BITMAPFILEHEADER (14 bytes)
|
||||
### 15.8.2 BITMAPFILEHEADER (14 bytes)
|
||||
|
||||
| Offset | Tamaño | Campo | Descripción |
|
||||
|---|---|---|---|
|
||||
@@ -826,7 +826,7 @@ Un archivo `.bmp` se compone de estas partes, en este orden:
|
||||
| 8 | 2 | `bfReserved2` | Reservado, debe ser 0. |
|
||||
| 10 | 4 | `bfOffBits` | Offset en bytes donde comienzan los datos de píxeles. |
|
||||
|
||||
### 14.8.3 BITMAPINFOHEADER (40 bytes, versión más común)
|
||||
### 15.8.3 BITMAPINFOHEADER (40 bytes, versión más común)
|
||||
|
||||
| Offset | Tamaño | Campo | Descripción |
|
||||
|---|---|---|---|
|
||||
@@ -845,7 +845,7 @@ Un archivo `.bmp` se compone de estas partes, en este orden:
|
||||
**Resumen:** desde el offset 14 hasta el 53 (40 bytes) está toda la información que
|
||||
necesitamos para saber cómo leer los píxeles.
|
||||
|
||||
### 14.8.4 Datos de píxeles
|
||||
### 15.8.4 Datos de píxeles
|
||||
|
||||
Los píxeles comienzan en el offset indicado por `bfOffBits` (campo del archivo, offset 10).
|
||||
|
||||
@@ -868,17 +868,17 @@ bytesPorFila = ((biWidth * 3 + 3) / 4) * 4
|
||||
|
||||
Las filas reales se leen desde el final hacia el principio si la imagen es bottom-up.
|
||||
|
||||
### 14.8.5 Paleta (solo para 1, 4 u 8 bpp)
|
||||
### 15.8.5 Paleta (solo para 1, 4 u 8 bpp)
|
||||
|
||||
Para 8 bits por píxel, cada píxel es 1 byte que es un **índice** a una tabla de 256 colores
|
||||
(paleta). Cada entrada de la paleta ocupa 4 bytes: `B`, `G`, `R`, reservado (0).
|
||||
La paleta comienza inmediatamente después de la cabecera de bits (offset `14 + biSize`).
|
||||
|
||||
### 14.8.6 Anatomía de un BMP real: ejemplo byte a byte
|
||||
### 15.8.6 Anatomía de un BMP real: ejemplo byte a byte
|
||||
|
||||
Las tablas de arriba describen el formato en abstracto. Ahora veamos un **BMP real**, chiquito
|
||||
a propósito (5×3 píxeles, 102 bytes), para seguir cada campo sobre los bytes mismos. Es el
|
||||
mismo archivo que usamos más adelante para verificar el Ejercicio 14.8.
|
||||
mismo archivo que usamos más adelante para verificar el Ejercicio 15.8.
|
||||
|
||||
<img width="150" alt="Render de ejemplo-bmp-5x3.bmp: grilla de 5×3 píxeles con los bordes dibujados en negro"
|
||||
style="image-rendering: pixelated;"
|
||||
@@ -958,7 +958,7 @@ buffer copiá la fila `i` del archivo a la fila `height - 1 - i` de la imagen.
|
||||
> coordenada (2, 1) —columna 2, fila 1— y es **verde**: `RGB(34, 177, 76)`. Es una forma
|
||||
> rapidísima de saber si tu programa leyó bien las cabeceras y el padding.
|
||||
|
||||
### 14.8.7 Cómo leer un BMP (flujo sugerido)
|
||||
### 15.8.7 Cómo leer un BMP (flujo sugerido)
|
||||
|
||||
1. Abrir el archivo en binario (`rb`).
|
||||
2. Leer los 14 bytes del **BITMAPFILEHEADER**.
|
||||
@@ -974,7 +974,7 @@ buffer copiá la fila `i` del archivo a la fila `height - 1 - i` de la imagen.
|
||||
> el byte menos significativo va primero. Leerlos con `fread` en un `uint32_t` funciona bien en
|
||||
> máquinas little-endian (x86/x64).
|
||||
|
||||
## 14.9 Mostrar la imagen en pantalla (opcional): SDL2
|
||||
## 15.9 Mostrar la imagen en pantalla (opcional): SDL2
|
||||
|
||||
Hasta acá todo el trabajo fue **leer e interpretar** bytes. Un objetivo opcional y muy motivador es
|
||||
**mostrar la imagen** en una ventana. C no trae esto en su biblioteca estándar: dibujar ventanas es
|
||||
@@ -984,7 +984,7 @@ para empezar es **SDL2**.
|
||||
> Esta sección es **opcional** y va más allá del objetivo central del capítulo (leer archivos).
|
||||
> SDL2 es una **dependencia externa**; si tu entorno no la tiene, podés saltearla sin problema.
|
||||
|
||||
### 14.9.1 La idea
|
||||
### 15.9.1 La idea
|
||||
|
||||
Ya tenés los píxeles en memoria, con 3 bytes por píxel. SDL2 ofrece una función que **envuelve un
|
||||
buffer de píxeles** en una superficie dibujable, sin copiar los datos:
|
||||
@@ -1013,7 +1013,7 @@ Si en cambio guardaste los píxeles en el orden `B, G, R` tal cual vienen en BMP
|
||||
**intercambian** entre rojo y azul. Este es el error más común: colores correctos pero con rojo y
|
||||
azul cambiados.
|
||||
|
||||
### 14.9.2 Programa mínimo de visualización
|
||||
### 15.9.2 Programa mínimo de visualización
|
||||
|
||||
Este programa asume que ya cargaste la imagen en `pixels` (un buffer `width * height * 3` en orden
|
||||
`R, G, B`, con la fila `0` **arriba**). Muestra la ventana hasta que la cierres o presiones una
|
||||
@@ -1060,14 +1060,14 @@ int main(void) {
|
||||
}
|
||||
```
|
||||
|
||||
### 14.9.3 El detalle de las filas: BMP es bottom-up
|
||||
### 15.9.3 El detalle de las filas: BMP es bottom-up
|
||||
|
||||
SDL espera la **fila 0 arriba**. BMP, en cambio, guarda la imagen **de abajo hacia arriba**. Si
|
||||
volcás los píxeles tal como los leíste, la imagen va a aparecer **invertida verticalmente**.
|
||||
La solución es copiar cada fila a su posición espejada (`fila destino = height - 1 - fila origen`)
|
||||
al momento de cargar el buffer.
|
||||
|
||||
### 14.9.4 Compilar y enlazar
|
||||
### 15.9.4 Compilar y enlazar
|
||||
|
||||
SDL2 se enlaza como cualquier biblioteca externa. Con `gcc` y la utilidad `sdl2-config`:
|
||||
|
||||
@@ -1083,14 +1083,14 @@ distribuciones Linux, el paquete suele llamarse `libsdl2-dev`.
|
||||
> explícito del capítulo. Esta sección es la excepción deliberada y por eso queda marcada como
|
||||
> opcional.
|
||||
|
||||
## 14.10 Ejercicios: archivos binarios
|
||||
## 15.10 Ejercicios: archivos binarios
|
||||
|
||||
Estos ejercicios ponen a prueba la segunda mitad del capítulo: archivos binarios con `fread` y
|
||||
`fwrite` (sección 14.4), el formato PPM (14.5), arenas (14.6), errores (14.7) y el formato BMP
|
||||
(14.8). La regla fundamental de la sección 14.3 sigue en pie: **ningún ejercicio incluye código
|
||||
`fwrite` (sección 15.4), el formato PPM (15.5), arenas (15.6), errores (15.7) y el formato BMP
|
||||
(15.8). La regla fundamental de la sección 15.3 sigue en pie: **ningún ejercicio incluye código
|
||||
de solución**.
|
||||
|
||||
### Ejercicio 14.4 — Lectura binaria con `fread` (binario, intermedio)
|
||||
### Ejercicio 15.4 — Lectura binaria con `fread` (binario, intermedio)
|
||||
|
||||
**Conceptos** · Archivos binarios, `fopen` con `rb`, `fread`, buffers de bytes
|
||||
|
||||
@@ -1127,21 +1127,21 @@ y leer todo con `fread(buf, 1, size, fp)`. Verificar que `fread` leyó lo espera
|
||||
- [ ] Muestra primeros N bytes en formato legible (hex).
|
||||
- [ ] Libera memoria con `free()` y cierra archivo.
|
||||
|
||||
### Ejercicio 14.5 — Lectura binaria usando arena (arenas + binario, intermedio)
|
||||
### Ejercicio 15.5 — Lectura binaria usando arena (arenas + binario, intermedio)
|
||||
|
||||
**Conceptos** · Arenas (bump allocator), lectura binaria, bloques grandes
|
||||
|
||||
**Consigna** · Repetir el Ejercicio 14.4, pero **reservando toda la memoria necesaria desde una arena**
|
||||
**Consigna** · Repetir el Ejercicio 15.4, pero **reservando toda la memoria necesaria desde una arena**
|
||||
en lugar de llamar `malloc` directamente para el buffer completo. El programa debe:
|
||||
- Crear una arena con capacidad suficiente para alojar el contenido completo del archivo
|
||||
(o un bloque razonable si se desea leer por chunks; para este ejercicio, leer completo).
|
||||
- Leer el archivo binario completo dentro de esa arena (usando el espacio de la arena).
|
||||
- Mostrar tamaño y primeros N bytes (igual salida que 14.4).
|
||||
- Mostrar tamaño y primeros N bytes (igual salida que 15.4).
|
||||
- Liberar **todo junto** al final (reiniciar cursor o liberar el bloque de arena completo). **No**
|
||||
hacer `free` por byte/elemento.
|
||||
|
||||
**Entrada** · Ruta del archivo binario y `N`.
|
||||
**Salida** · Igual que Ejercicio 14.4.
|
||||
**Salida** · Igual que Ejercicio 15.4.
|
||||
|
||||
**Identificadores sugeridos** · `arena`, `arenaBlock`, `capacity`, `offset`
|
||||
|
||||
@@ -1158,7 +1158,7 @@ es suficiente para bytes). Leer el archivo completo dentro del espacio asignado
|
||||
- [ ] Libera memoria con **un único `free`** (bloque de arena). No hay frees por partes.
|
||||
- [ ] No hay fugas de memoria ni double-free.
|
||||
|
||||
### Ejercicio 14.6 — Escritura binaria estructurada (binario, avanzado)
|
||||
### Ejercicio 15.6 — Escritura binaria estructurada (binario, avanzado)
|
||||
|
||||
**Conceptos** · `fwrite`, estructuras, archivos binarios, persistencia
|
||||
|
||||
@@ -1196,23 +1196,23 @@ Verificar cantidad leída.
|
||||
- [ ] Maneja memoria con `malloc/free` adecuadamente.
|
||||
- [ ] No corrompe datos al escribir/leer.
|
||||
|
||||
### Ejercicio 14.7 — Persistencia binaria con arena (binario + arenas, avanzado)
|
||||
### Ejercicio 15.7 — Persistencia binaria con arena (binario + arenas, avanzado)
|
||||
|
||||
**Conceptos** · Arenas, `fwrite`/`fread`, buffers desde arena
|
||||
|
||||
**Consigna** · Modificar el Ejercicio 14.6 para que **el buffer de lectura** (donde se cargan
|
||||
**Consigna** · Modificar el Ejercicio 15.6 para que **el buffer de lectura** (donde se cargan
|
||||
los puntos leídos) se reserve **desde una arena**, en lugar de `malloc` directo. También
|
||||
puede reservarse el arreglo original desde arena si se desea. El objetivo es practicar
|
||||
lectura binaria usando espacio de arena.
|
||||
|
||||
**Entrada/Salida** · Igual que Ejercicio 14.6.
|
||||
**Entrada/Salida** · Igual que Ejercicio 15.6.
|
||||
**Criterios de aceptación**
|
||||
- [ ] Buffer de lectura reservado desde arena.
|
||||
- [ ] Lectura con `fread` correcta.
|
||||
- [ ] Verificación OK.
|
||||
- [ ] Liberación con único `free` del bloque de arena (sin frees individuales).
|
||||
|
||||
### Ejercicio 14.8 — (JEFE) Leer un archivo BMP pixel a pixel
|
||||
### Ejercicio 15.8 — (JEFE) Leer un archivo BMP pixel a pixel
|
||||
|
||||
**Conceptos** · Cabeceras binarias (`fread` de estructuras), little-endian, `fseek`, `ftell`,
|
||||
interpretación de píxeles, `malloc/free` y/o arenas (opcional), validación de formato.
|
||||
@@ -1262,12 +1262,12 @@ Salida: Archivo: imagen.bmp
|
||||
- Podés usar una estructura simple para el conteo de colores (p.ej. guardar los 8 colores más
|
||||
frecuentes o un arreglo de conteos).
|
||||
- Opción extra: repetir la lectura usando una **arena** para los buffers de píxeles.
|
||||
- **Archivo de prueba ideal**: el BMP de 5×3 de la sección 14.8.6 (102 bytes, tres filas de
|
||||
- **Archivo de prueba ideal**: el BMP de 5×3 de la sección 15.8.6 (102 bytes, tres filas de
|
||||
color sólido). Es tan chico que verificás todo a mano: `bfOffBits = 54`, `rowSize = 16` (15
|
||||
bytes de color + 1 de relleno), **3 colores × 15 píxeles** y el píxel central (2, 1) debe dar
|
||||
`R=34 G=177 B=76`. El archivo está en `assets/img/ejemplo-bmp-5x3.bmp`.
|
||||
- La documentación del formato está en la sección 14.8. Si querés mostrar la imagen, mirá la
|
||||
sección 14.9 (SDL2, opcional).
|
||||
- La documentación del formato está en la sección 15.8. Si querés mostrar la imagen, mirá la
|
||||
sección 15.9 (SDL2, opcional).
|
||||
|
||||
**Criterios de aceptación**
|
||||
- [ ] Valida la firma `BM` antes de continuar.
|
||||
@@ -1279,4 +1279,4 @@ Salida: Archivo: imagen.bmp
|
||||
- [ ] Maneja archivos inexistentes o corruptos con mensajes de error claros.
|
||||
- [ ] Libera memoria correctamente (con `free` o un solo `free` de la arena).
|
||||
- [ ] (Extra) Implementa la versión con arena y verifica que da el mismo resultado.
|
||||
- [ ] (Extra) Muestra la imagen en una ventana con SDL2 (ver sección 14.9).
|
||||
- [ ] (Extra) Muestra la imagen en una ventana con SDL2 (ver sección 15.9).
|
||||
@@ -1,4 +1,4 @@
|
||||
# Capítulo 15 — Tipos más usados de C
|
||||
# Capítulo 16 — Tipos más usados de C
|
||||
|
||||
> Capítulo avanzado. Se apoya en tipos primitivos (`02`), operadores (`03`), arreglos (`06`),
|
||||
> punteros (`07`) y `struct` (`08`).
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
---
|
||||
|
||||
## 15.1 ¿Por qué no alcanza con un `int`?
|
||||
## 16.1 ¿Por qué no alcanza con un `int`?
|
||||
|
||||
Un `int` resuelve muchísimos casos, pero **no responde de forma portable** tres preguntas:
|
||||
|
||||
@@ -53,7 +53,7 @@ datos** (valores en bits):
|
||||
|
||||
---
|
||||
|
||||
## 15.2 El mapa de los tipos
|
||||
## 16.2 El mapa de los tipos
|
||||
|
||||
Casi ningún tipo "con nombre" es palabra del lenguaje: son **typedefs** de una cabecera. Estos son
|
||||
los que vas a usar todo el tiempo (tamaño típico en un sistema de 64 bits):
|
||||
@@ -78,7 +78,7 @@ los que vas a usar todo el tiempo (tamaño típico en un sistema de 64 bits):
|
||||
|
||||
---
|
||||
|
||||
## 15.3 `size_t` — los tamaños
|
||||
## 16.3 `size_t` — los tamaños
|
||||
|
||||
**Cabecera:** `<stddef.h>`
|
||||
|
||||
@@ -101,7 +101,7 @@ uses en un `for` inverso (`for (size_t i = n - 1; i >= 0; i--)` es **infinito**)
|
||||
|
||||
---
|
||||
|
||||
## 15.4 `wchar_t` — caracteres anchos
|
||||
## 16.4 `wchar_t` — caracteres anchos
|
||||
|
||||
**Cabecera:** `<stddef.h>`
|
||||
|
||||
@@ -135,7 +135,7 @@ clave no es "agrandar" el tipo, sino **elegir el correcto**. **Se imprimen con `
|
||||
|
||||
---
|
||||
|
||||
## 15.5 `NULL` — el puntero nulo
|
||||
## 16.5 `NULL` — el puntero nulo
|
||||
|
||||
**Cabecera:** `<stddef.h>`
|
||||
|
||||
@@ -148,7 +148,7 @@ conceptual.
|
||||
|
||||
---
|
||||
|
||||
## 15.6 `bool` — verdadero o falso
|
||||
## 16.6 `bool` — verdadero o falso
|
||||
|
||||
**Cabecera:** `<stdbool.h>` (C99; en C23, palabra clave)
|
||||
|
||||
@@ -161,7 +161,7 @@ usarlo:** si necesitás más de dos estados, un `enum` expresa mejor la intenci
|
||||
|
||||
---
|
||||
|
||||
## 15.7 Enteros de ancho exacto
|
||||
## 16.7 Enteros de ancho exacto
|
||||
|
||||
**Cabecera:** `<stdint.h>`
|
||||
|
||||
@@ -205,7 +205,7 @@ printf("%llu\n", (unsigned long long)big);
|
||||
|
||||
---
|
||||
|
||||
## 15.8 ¿Tengo que dejar de usar `int`?
|
||||
## 16.8 ¿Tengo que dejar de usar `int`?
|
||||
|
||||
**No.** Estos tipos **no reemplazan** a `int`: lo **complementan** para casos puntuales. El `int`
|
||||
sigue siendo el tipo por defecto para números enteros comunes.
|
||||
@@ -223,7 +223,7 @@ Pasá a un **tipo preciso** solo cuando **exista un motivo**:
|
||||
- **`wchar_t` / `char32_t`** → un carácter que no entra en un `char`.
|
||||
|
||||
> **Y ojo con el revés:** usar un tipo chico "por las dudas" también trae problemas. `int8_t` llega
|
||||
> hasta 127 (ver la tabla de 15.7): si lo usás para contar, se desborda enseguida. Y encima la
|
||||
> hasta 127 (ver la tabla de 16.7): si lo usás para contar, se desborda enseguida. Y encima la
|
||||
> aritmética se hace en `int` igual.
|
||||
|
||||
```c
|
||||
@@ -255,7 +255,7 @@ int c = a + b; /* 200: la suma se calcula en int, y al achicar se desborda */
|
||||
|
||||
---
|
||||
|
||||
## 15.9 ¿Los tipos chicos ahorran memoria?
|
||||
## 16.9 ¿Los tipos chicos ahorran memoria?
|
||||
|
||||
**Depende de dónde.** Guardar **muchos** valores en tipos chicos sí ahorra memoria; una variable
|
||||
suelta, no.
|
||||
@@ -290,7 +290,7 @@ struct Color2 { int r, g, b; }; /* 12 bytes */
|
||||
|
||||
---
|
||||
|
||||
## 15.10 Errores comunes
|
||||
## 16.10 Errores comunes
|
||||
|
||||
- Comparar un `int` negativo con `sizeof` o `strlen` (el `-1` se vuelve `SIZE_MAX`).
|
||||
- Guardar un tamaño (`sizeof`, tamaño de un archivo) en un `int`.
|
||||
@@ -301,14 +301,14 @@ struct Color2 { int r, g, b; }; /* 12 bytes */
|
||||
|
||||
---
|
||||
|
||||
## 15.11 Ejercicios
|
||||
## 16.11 Ejercicios
|
||||
|
||||
> De **noob** a **pro**, con dificultad creciente. Cada ejercicio declara sus conceptos objetivo;
|
||||
> resolvelos **usando esos conceptos**. Trae un **escenario de prueba** (entrada/salida esperada,
|
||||
> nunca el algoritmo) para que compares lo que imprimís. Compilá con un estándar moderno (C11 o C23)
|
||||
> y avisos activos (`-Wall -Wextra`).
|
||||
|
||||
### Ejercicio 15.1 — Radiografía de tipos
|
||||
### Ejercicio 16.1 — Radiografía de tipos
|
||||
|
||||
**Conceptos** · `sizeof`, `size_t`, `printf` (`%zu`), tipos de `<stddef.h>` y `<stdint.h>`
|
||||
|
||||
@@ -342,7 +342,7 @@ LP64 (Linux/macOS 64-bit) LLP64 (Windows 64-bit)
|
||||
|
||||
---
|
||||
|
||||
### Ejercicio 15.2 — Sumar con `size_t`
|
||||
### Ejercicio 16.2 — Sumar con `size_t`
|
||||
|
||||
**Conceptos** · `size_t`, arreglos, `for`, casos borde
|
||||
|
||||
@@ -369,7 +369,7 @@ count = 1 ; [-5] -> -5
|
||||
|
||||
---
|
||||
|
||||
### Ejercicio 15.3 — El índice que se convierte en gigante
|
||||
### Ejercicio 16.3 — El índice que se convierte en gigante
|
||||
|
||||
**Conceptos** · conversiones con/sin signo, `size_t`, comparaciones
|
||||
|
||||
@@ -395,7 +395,7 @@ explicación: -1 convertido a size_t = SIZE_MAX (18446744073709551615), y SIZE_M
|
||||
|
||||
---
|
||||
|
||||
### Ejercicio 15.4 — Texto que no entra en un byte
|
||||
### Ejercicio 16.4 — Texto que no entra en un byte
|
||||
|
||||
**Conceptos** · `wchar_t`, `L""`, `%lc`, `%ls`, `<uchar.h>`
|
||||
|
||||
@@ -426,7 +426,7 @@ contraste: guardar 'ñ' en un char y usar %c da basura o un byte suelto.
|
||||
|
||||
---
|
||||
|
||||
### Ejercicio 15.5 — El entero de ancho exacto (pro)
|
||||
### Ejercicio 16.5 — El entero de ancho exacto (pro)
|
||||
|
||||
**Conceptos** · `<stdint.h>`, tipos de ancho exacto, portabilidad
|
||||
|
||||
@@ -457,7 +457,7 @@ total = 123456789012345ULL (uint64_t) -> 123456789012345
|
||||
|
||||
---
|
||||
|
||||
## 15.12 Cierre
|
||||
## 16.12 Cierre
|
||||
|
||||
Los tipos de C no son un adorno: son la forma de decir **qué querés representar** y **de qué
|
||||
tamaño**. `size_t` para tamaños, `uintN_t`/`intN_t` para ancho exacto, `bool` para verdades,
|
||||
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user