Buscar una palabra en un archivo sin desbordar el búfer
Lectura línea por línea con fgets, que nunca escribe fuera del espacio reservado, y códigos de salida que otro programa puede usar.
El problema
Leer texto en C con las funciones equivocadas es el origen clásico de los desbordamientos. Hay que leer un archivo de cualquier tamaño con un búfer fijo y sin riesgo.
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
if (argc < 3) { fprintf(stderr, "Uso: %s archivo palabra\n", argv[0]); return 1; }
FILE *f = fopen(argv[1], "r");
if (!f) { perror(argv[1]); return 1; }
char linea[1024];
long n = 0, hallazgos = 0;
while (fgets(linea, sizeof linea, f)) { /* nunca escribe fuera del búfer */
n++;
if (strstr(linea, argv[2])) {
printf("%ld: %s", n, linea);
hallazgos++;
}
}
fclose(f);
printf("\n%ld coincidencias en %ld líneas\n", hallazgos, n);
return hallazgos ? 0 : 2;
}
Por qué está escrito así
- fgets recibe el tamaño del búfer y se detiene ahí: es la diferencia con gets, que no lo sabe y por eso fue eliminada del lenguaje.
- sizeof linea le pasa el tamaño real; si mañana cambia el 1024, el resto sigue bien.
- perror imprime el motivo del sistema ("No such file", "Permission denied") sin que haya que adivinarlo.
- El código de salida distingue tres casos: encontró, no encontró, o hubo un error de uso.
Guardalo como buscar.c y corré: cc -Wall -o buscar buscar.c && ./buscar buscar.c fgets
Una línea de más de 1023 caracteres se lee en dos pedazos: se cuenta como dos líneas y una palabra partida justo en el corte no se encuentra. Para líneas arbitrarias está getline.
Adaptalo a tu caso con IA
El botón copia este prompt con el código pegado debajo. Reemplazá los corchetes con lo tuyo y pegalo en ChatGPT, Claude, Gemini o Copilot.
Tengo este buscador de texto en C con fgets. Adaptalo para que maneje líneas de cualquier largo con getline, acepte la opción -i para ignorar mayúsculas y -c para mostrar solo la cantidad, y libere toda la memoria. Compilá mentalmente con -Wall -Wextra y decime si quedaría algún aviso. Estándar [C99 o C11], sistema [LINUX, MACOS].
Ejemplo escrito y revisado a mano.
Comentarios
Todavía no hay comentarios. El primero puede ser el tuyo.
¿Lo adaptaste a algo tuyo?
Contame qué resolviste con esto, o qué le faltó.