Search code examples
cfile-iofgetsgetlinefgetc

fgetc vs getline or fgets - which is most flexible


I am reading data from a regular file and I was wondering which would allow for the most flexibility.

I have found that both fgets and getline both read in a line (one with a maximum number of characters, the other with dynamic memory allocation). In the case of fgets, if the length of the line is bigger than the given size, the rest of the line would not be read but remain buffered in the stream. With getline, I am worried that it may attempt to assign a large block of memory for an obscenely long line.

The obvious solution for me seems to be turning to fgetc, but this comes with the problem that there will be many calls to the function, thereby resulting in the read process being slow.

Is this compromise in either case between flexibility and efficiency unavoidable, or can it worked through?


Solution

  • Much is case dependent.

    getline() is not part of the standard C library. Its functionality may differ - depends on the implementation and what other standards it follows - thus an advantage for the standard fgetc()/fgets().

    ... case between flexibility and efficiency unavoidable, ...

    OP is missing the higher priorities.

    • Functionality - If code cannot function right with the selected function, why use it? Example: fgets() and reading null characters create issues.

    • Clarity - without clarity, feel the wrath of the poor soul who later has to maintain the code.


    would allow for the most flexibility. (?)

    • fgetc() allows for the most flexibility at the low level - yet helper functions using it to read lines tend to fail corner cases.

    • fgets() allows for the most flexibility at mid level - still have to deal with long lines and those with embedded null characters, but at least the low level of slogging in the weeds is avoided.

    • getline() useful when high portability not needed and risks of allowing the user to overwhelm resources is not a concern.


    For robust handing of user/file input to read a line, create a wrapping function (e.g. int my_read_line(size_t buf, char *buf, FILE *f)) and call that and only that in user code. Then when issues arise, they can be handled locally, regardless of the low level input function selected.