C read file line by line

前端 未结 17 2169
后悔当初
后悔当初 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:21
    const char *readLine(FILE *file, char* line) {
    
        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);
        return line;
    
    }
    
    
    char linebuffer[256];
    while (!feof(myFile)) {
        const char *line = readLine(myFile, linebuffer);
        printf("%s\n", line);
    }
    

    note that the 'line' variable is declared in calling function and then passed, so your readLine function fills predefined buffer and just returns it. This is the way most of C libraries work.

    There are other ways, which I'm aware of:

    • defining the char line[] as static (static char line[MAX_LINE_LENGTH] -> it will hold it's value AFTER returning from the function). -> bad, the function is not reentrant, and race condition can occur -> if you call it twice from two threads, it will overwrite it's results
    • malloc()ing the char line[], and freeing it in calling functions -> too many expensive mallocs, and, delegating the responsibility to free the buffer to another function (the most elegant solution is to call malloc and free on any buffers in same function)

    btw, 'explicit' casting from char* to const char* is redundant.

    btw2, there is no need to malloc() the lineBuffer, just define it char lineBuffer[128], so you don't need to free it

    btw3 do not use 'dynamic sized stack arrays' (defining the array as char arrayName[some_nonconstant_variable]), if you don't exactly know what are you doing, it works only in C99.

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

    You make the mistake of returning a pointer to an automatic variable. The variable line is allocated in the stack and only lives as long as the function lives. You are not allowed to return a pointer to it, because as soon as it returns the memory will be given elsewhere.

    const char* func x(){
        char line[100];
        return (const char*) line; //illegal
    }
    

    To avoid this, you either return a pointer to memory which resides on the heap eg. lineBuffer and it should be the user's responsibility to call free() when he is done with it. Alternatively you can ask the user to pass you as an argument a memory address on which to write the line contents at.

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

    Implement method to read, and get content from a file (input1.txt)

    #include <stdio.h>
    #include <stdlib.h>
    
    void testGetFile() {
        // open file
        FILE *fp = fopen("input1.txt", "r");
        size_t len = 255;
        // need malloc memory for line, if not, segmentation fault error will occurred.
        char *line = malloc(sizeof(char) * len);
        // check if file exist (and you can open it) or not
        if (fp == NULL) {
            printf("can open file input1.txt!");
            return;
        }
        while(fgets(line, len, fp) != NULL) {
            printf("%s\n", line);
        }
        free(line);
    }
    

    Hope this help. Happy coding!

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

    Provide a portable and generic getdelim function, test passed via msvc, clang, gcc.

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    ssize_t
    portabl_getdelim(char ** restrict linep,
                     size_t * restrict linecapp,
                     int delimiter,
                     FILE * restrict stream) {
        if (0 == *linep) {
            *linecapp = 8;
            *linep = malloc(*linecapp);
            if (0 == *linep) {
                return EOF;
            }
        }
    
        ssize_t linelen = 0;
        int c = 0;
        char *p = *linep;
    
        while (EOF != (c = fgetc(stream))) {
            if (linelen == (ssize_t) *linecapp - 1) {
                *linecapp <<= 1;
                char *p1 = realloc(*linep, *linecapp);
                if (0 == *p1) {
                    return EOF;
                }
                p = p1 + linelen;
            }
            *p++ = c;
            linelen++;
    
            if (delimiter == c) {
                *p = 0;
                return linelen;
            }
        }
        return EOF == c ? EOF : linelen;
    }
    
    
    int
    main(int argc, char **argv) {
        const char *filename = "/a/b/c.c";
        FILE *file = fopen(filename, "r");
        if (!file) {
            perror(filename);
            return 1;
        }
    
        char *line = 0;
        size_t linecap = 0;
        ssize_t linelen;
    
        while (0 < (linelen = portabl_getdelim(&line, &linecap, '\n', file))) {
            fwrite(line, linelen, 1, stdout);
        }
        if (line) {
            free(line);
        }
        fclose(file);   
    
        return 0;
    }
    
    0 讨论(0)
  • 2020-11-22 04:26
    //open and get the file handle
    FILE* fh;
    fopen_s(&fh, filename, "r");
    
    //check if file exists
    if (fh == NULL){
        printf("file does not exists %s", filename);
        return 0;
    }
    
    
    //read line by line
    const size_t line_size = 300;
    char* line = malloc(line_size);
    while (fgets(line, line_size, fh) != NULL)  {
        printf(line);
    }
    free(line);    // dont forget to free heap memory
    
    0 讨论(0)
提交回复
热议问题