Search code examples
cposixfgetsgetline

Using getline vs fgets for basic file printing


I am using the following to print the lines of a file:

int main() {

    FILE *fptr = fopen("test20k.csv", "r");
    char buffer[MAXLINE];

    while (fgets(buffer, sizeof(buffer), fptr) != NULL)
        printf("%s", buffer);
    putchar('\n');

    return 0;

}

How would the same thing be done using getline? Here is a similar question which is more conceptual: getline() vs. fgets(): Control memory allocation.


Solution

  • You simply check getline(3) - Linux manual page to determine the appropriate parameter types to pass and the return type to handle and how getline indicates success/failure.

    Then all that is needed is to replace fgets() with getline() in your code. All line-oriented input functions read and include the trailing '\n', so no change there. However, note that getline() allocates storage for your buffer, so you will need to free() the buffer when you are done with it -- requiring that your include stdlib.h in addition to stdio.h.

    Further, you note that getline is not part of the standard C library. Instead getline is a POSIX function, so not every implementation of C need provide it, so you may have portability issues.

    That's basically it. Though, in your code you should not use hardcoded filenames. That is one reason why main() accepts parameters. So simply pass the filename to read as the first argument to your program (you can also read from stdin by default if no argument is provided)

    Putting it all together, as a minimum implementation, you could do:

    #include <stdio.h>
    #include <stdlib.h>
    
    int main (int argc, char **argv) {
    
        size_t n = 0;           /* initial alloc size, 0 - getline decides */
        char *buffer = NULL;    /* pointer to block of mem holding input */
        /* use filename provided as 1st argument (stdin by default) */
        FILE *fptr = argc > 1 ? fopen (argv[1], "r") : stdin;
    
        if (!fptr) {    /* validate file open for reading */
            perror ("file open failed");
            return 1;
        }
    
        /* you pass the address of your buffer and a pointer to n */
        while (getline (&buffer, &n, fptr) != -1)
            printf("%s", buffer);
        putchar('\n');
    
        if (fptr != stdin)   /* close file if not stdin */
            fclose (fptr);
    
        free (buffer);      /* getline allocates, don't forget to free */
    
        return 0;
    }
    

    Look things over and let me know if you have further questions.

    Example Input File

    $ cat dat/captnjack.txt
    This is a tale
    Of Captain Jack Sparrow
    A Pirate So Brave
    On the Seven Seas.
    

    Example Use/Output

    $ ./bin/getline_file dat/captnjack.txt
    This is a tale
    Of Captain Jack Sparrow
    A Pirate So Brave
    On the Seven Seas.