C read file line by line

前端 未结 17 2191
后悔当初
后悔当初 2020-11-22 03:45

I wrote this function to read a line from a file:

const char *readLine(FILE *file) {

    if (file == NULL) {
        printf(\"Error: file pointer is null.\"         


        
相关标签:
17条回答
  • 2020-11-22 04:03

    Some things wrong with the example:

    • you forgot to add \n to your printfs. Also error messages should go to stderr i.e. fprintf(stderr, ....
    • (not a biggy but) consider using fgetc() rather than getc(). getc() is a macro, fgetc() is a proper function
    • getc() returns an int so ch should be declared as an int. This is important since the comparison with EOF will be handled correctly. Some 8 bit character sets use 0xFF as a valid character (ISO-LATIN-1 would be an example) and EOF which is -1, will be 0xFF if assigned to a char.
    • There is a potential buffer overflow at the line

      lineBuffer[count] = '\0';
      

      If the line is exactly 128 characters long, count is 128 at the point that gets executed.

    • As others have pointed out, line is a locally declared array. You can't return a pointer to it.

    • strncpy(count + 1) will copy at most count + 1 characters but will terminate if it hits '\0' Because you set lineBuffer[count] to '\0' you know it will never get to count + 1. However, if it did, it would not put a terminating '\0' on, so you need to do it. You often see something like the following:

      char buffer [BUFFER_SIZE];
      strncpy(buffer, sourceString, BUFFER_SIZE - 1);
      buffer[BUFFER_SIZE - 1] = '\0';
      
    • if you malloc() a line to return (in place of your local char array), your return type should be char* - drop the const.

    0 讨论(0)
  • 2020-11-22 04:04

    Use fgets() to read a line from a file handle.

    0 讨论(0)
  • 2020-11-22 04:05

    If your task is not to invent the line-by-line reading function, but just to read the file line-by-line, you may use a typical code snippet involving the getline() function (see the manual page here):

    #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);
    }
    
    0 讨论(0)
  • 2020-11-22 04:06

    Here is my several hours... Reading whole file line by line.

    char * readline(FILE *fp, char *buffer)
    {
        int ch;
        int i = 0;
        size_t buff_len = 0;
    
        buffer = malloc(buff_len + 1);
        if (!buffer) return NULL;  // Out of memory
    
        while ((ch = fgetc(fp)) != '\n' && ch != EOF)
        {
            buff_len++;
            void *tmp = realloc(buffer, buff_len + 1);
            if (tmp == NULL)
            {
                free(buffer);
                return NULL; // Out of memory
            }
            buffer = tmp;
    
            buffer[i] = (char) ch;
            i++;
        }
        buffer[i] = '\0';
    
        // Detect end
        if (ch == EOF && (i == 0 || ferror(fp)))
        {
            free(buffer);
            return NULL;
        }
        return buffer;
    }
    
    void lineByline(FILE * file){
    char *s;
    while ((s = readline(file, 0)) != NULL)
    {
        puts(s);
        free(s);
        printf("\n");
    }
    }
    
    int main()
    {
        char *fileName = "input-1.txt";
        FILE* file = fopen(fileName, "r");
        lineByline(file);
        return 0;
    }
    
    0 讨论(0)
  • 2020-11-22 04:10

    In your readLine function, you return a pointer to the line array (Strictly speaking, a pointer to its first character, but the difference is irrelevant here). Since it's an automatic variable (i.e., it's “on the stack”), the memory is reclaimed when the function returns. You see gibberish because printf has put its own stuff on the stack.

    You need to return a dynamically allocated buffer from the function. You already have one, it's lineBuffer; all you have to do is truncate it to the desired length.

        lineBuffer[count] = '\0';
        realloc(lineBuffer, count + 1);
        return lineBuffer;
    }
    

    ADDED (response to follow-up question in comment): readLine returns a pointer to the characters that make up the line. This pointer is what you need to work with the contents of the line. It's also what you must pass to free when you've finished using the memory taken by these characters. Here's how you might use the readLine function:

    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). */
    
    0 讨论(0)
  • 2020-11-22 04:10

    readLine() returns pointer to local variable, which causes undefined behaviour.

    To get around you can:

    1. Create variable in caller function and pass its address to readLine()
    2. Allocate memory for line using malloc() - in this case line will be persistent
    3. Use global variable, although it is generally a bad practice
    0 讨论(0)
提交回复
热议问题