C leer el archivo línea por línea

Resuelto lron asked hace 14 años • 0 respuestas

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é?

lron avatar Aug 17 '10 17:08 lron
Aceptado

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);
}
mbaitoff avatar Aug 17 '2010 11:08 mbaitoff
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);
Rob avatar Aug 30 '2016 21:08 Rob

En su readLinefunción, devuelve un puntero a la linematriz (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 printfha 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): readLinedevuelve 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 freecuando hayas terminado de usar la memoria tomada por estos personajes. Así es como puedes usar la readLinefunció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). */