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.
The problem
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;
}
Why it is written this way
- 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.
Adapt it to your case with AI
The button copies this prompt with the code pasted below it. Replace the brackets with your own details and paste it into ChatGPT, Claude, Gemini or 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].
Example written and reviewed by hand.
Comments
No comments yet. Yours can be the first.
Did you adapt it to something of yours?
Tell me what you solved with it, or what it was missing.