C leer el archivo línea por línea
Escribí esta función para leer una línea de un archivo:
const char *readLine(FILE *file) {
if (file == NULL) {
printf("Error: file pointer is null.");
exit(1);
}
int maximumLineLength = 128;
char *lineBuffer = (char *)malloc(sizeof(char) * maximumLineLength);
if (lineBuffer == NULL) {
printf("Error allocating memory for line buffer.");
exit(1);
}
char ch = getc(file);
int count = 0;
while ((ch != '\n') && (ch != EOF)) {
if (count == maximumLineLength) {
maximumLineLength += 128;
lineBuffer = realloc(lineBuffer, maximumLineLength);
if (lineBuffer == NULL) {
printf("Error reallocating space for line buffer.");
exit(1);
}
}
lineBuffer[count] = ch;
count++;
ch = getc(file);
}
lineBuffer[count] = '\0';
char line[count + 1];
strncpy(line, lineBuffer, (count + 1));
free(lineBuffer);
const char *constLine = line;
return constLine;
}
La función lee el archivo correctamente y, al usar printf, veo que la cadena constLine también se leyó correctamente.
Sin embargo, si uso la función, por ejemplo, así:
while (!feof(myFile)) {
const char *line = readLine(myFile);
printf("%s\n", line);
}
printf genera galimatías. ¿Por qué?
Si su tarea no es inventar la función de lectura línea por línea, sino simplemente leer el archivo línea por línea, puede usar un fragmento de código típico que involucra la getline()
función (consulte la página del manual aquí ):
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE * fp;
char * line = NULL;
size_t len = 0;
ssize_t read;
fp = fopen("/etc/motd", "r");
if (fp == NULL)
exit(EXIT_FAILURE);
while ((read = getline(&line, &len, fp)) != -1) {
printf("Retrieved line of length %zu:\n", read);
printf("%s", line);
}
fclose(fp);
if (line)
free(line);
exit(EXIT_SUCCESS);
}
FILE* filePointer;
int bufferLength = 255;
char buffer[bufferLength]; /* not ISO 90 compatible */
filePointer = fopen("file.txt", "r");
while(fgets(buffer, bufferLength, filePointer)) {
printf("%s\n", buffer);
}
fclose(filePointer);
En su readLine
función, devuelve un puntero a la line
matriz (Estrictamente hablando, un puntero a su primer carácter, pero la diferencia es irrelevante aquí). Dado que es una variable automática (es decir, está "en la pila"), la memoria se recupera cuando la función regresa. Ves un galimatías porque printf
ha puesto sus propias cosas en la pila.
Debe devolver un búfer asignado dinámicamente desde la función. Ya tienes uno, es lineBuffer
; todo lo que tienes que hacer es truncarlo a la longitud deseada.
lineBuffer[count] = '\0';
realloc(lineBuffer, count + 1);
return lineBuffer;
}
AÑADIDO (respuesta a la pregunta de seguimiento en el comentario): readLine
devuelve un puntero a los caracteres que componen la línea. Este puntero es lo que necesita para trabajar con el contenido de la línea. También es a lo que debes pasar free
cuando hayas terminado de usar la memoria tomada por estos personajes. Así es como puedes usar la readLine
función:
char *line = readLine(file);
printf("LOG: read a line: %s\n", line);
if (strchr(line, 'a')) { puts("The line contains an a"); }
/* etc. */
free(line);
/* After this point, the memory allocated for the line has been reclaimed.
You can't use the value of `line` again (though you can assign a new value
to the `line` variable if you want). */