1

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.

ShadowRanger
  • 143,180
  • 12
  • 188
  • 271

2 Answers2

1

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.
David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
0

fgets()/getline() are commonly used to read text.

Uncommonly, the input stream contain a null character '\0'.

fgets() reads a null character like any character. It does not stop reading the line of input.

The below only prints to the first null character encountered in the string - it lacks a distinction from a read null character and the appended null character that fgets() adds.

while (fgets(buffer, sizeof(buffer), fptr)) {
  printf("%s", buffer);  // Maybe stops too early?
}

getline(), though non-standard C, has an advantage as it returns the numbers of characters read. Printing can then print to the count returned, rather than only to the first null character.

size_t n = 0;
char *buffer = NULL;

ssize_t sz;
while ((sz = getline (&buffer, &n, fptr)) != -1) {
  fwrite(buffer, 1, sz, stdout);
}

free(buffer);

Notes: size_t n = 0; char *buffer = NULL; are the initial settings. getline (&buffer, &n, ...) receives the address of those 2 variables allowing it to update those two (due to re-allocation) as needed. Max buffer size is SIZE_MAX or the limits of the memory pool. We do not need to know how it works exactly within getline() as that is an implementation detail that varies.


Although null characters are uncommon is simple text files, I have found writing code that is best to be prepared for for null characters. They readily come up is reading a text file that is UTF16 encoded. Of course expecting an ASCII or UTF8 texting file and getting a UTF16 one is a problem, nicely printing thought null characters helps ID the issue.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • thanks for this answer. One question -- why do you set the `*buffer` to NULL? And why is &n = 0 as well. If everything is set to zero, what is the maximum buffer size you can use, or how does that work exactly? –  Sep 06 '19 at 05:12