Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does fgetc return EOF on every call after end-of-file reached?

Tags:

c

libc

Given the following C code:

int eofCount = 0;
while (true) {
    int c = fgetc(stdin); 
    if (c == EOF) eofCount++;
}

Will eofCount ever become greater than 1?

I can't find anything in C docs describing what happens with fgetc after EOF has been reached once. I know I can do this book-keeping myself, but if the stdlib does it for me that'd be great.

I'm not looking for code snippets because I've already try this with glibc and in fact eofCount is incremented past EOF. I would like stdlib source code reference or spec that confirms this is the defined behavior. Relying on undefined behavior could lead to problems down the road.

like image 457
Alexandre Avatar asked Dec 24 '22 19:12

Alexandre


2 Answers

As long as you're not reading from an interactive Linux terminal (i.e. you do not open a file or pipe stdin from some other file/process), once you read EOF all future reads will also read EOF.

If you are reading from a Linux terminal, pressing the key sequence for EOF (CTRL-D on Linux) will read as EOF but you can still enter in more characters and read them.

From section 7.21.7.1 of the C standard:

3 If the end-of-file indicator for the stream is set, or if the stream is at end-of-file, the end-of-file indicator for the stream is set and the fgetc function returns EOF. Otherwise, the fgetc function returns the next character from the input stream pointed to by stream. If a read error occurs, the error indicator for the stream is set and the fgetc function returns EOF.

like image 180
dbush Avatar answered Apr 28 '23 06:04

dbush


Does fgetc return EOF on every call after end-of-file reached?

It depends of 2 indicators and I/O function calls.


Although not mentioned by OP, there are 2 reasons why fgetc(stdin); returns EOF and how they affect following fgetc() calls is not symmetric. Further, use of various I/O functions affect 2 indicators that in turn affect following fgetc() calls

End-of-file.
Input error.


The C spec is explicit on the end-of-file indicator causing subsequent EOF.

If the end-of-file indicator for the input stream pointed to by stream is not set and a next character is present, the fgetc function obtains that character ... C11 §7.21.7.1 2

When end-of-file occurs or had occurred, a persistent flag is set: end-of-file indicator, so subsequent calls to fgetc() will return EOF.

If the end-of-file indicator for the stream is set, or if the stream is at end-of-file, the end-of-file indicator for the stream is set and the fgetc function returnsEOF ... §7.21.7.1 3


When a rare input error occurs, fgetc() returns EOF, but that event does not set the end-of-file indicator, but an error indicator is set. Subsequent calls do not necessarily return EOF, even though a error indicator is set. IMO, the C spec is insufficiency clear on this point.

If a read error occurs, the error indicator for the stream is set and the fgetc function returns EOF §7.21.7.1 3


A call to feof(), and ferror() can be used to distinguish what caused the EOF, yet also may reflect prior I/O activity. Thus good code promptly checks these functions after an EOF is returned and clears them if following I/O is to occur.


The end-of-file indicator and error indicator can be cleared with void clearerr(FILE *stream);

The rewind() function clears the error indicator.

ungetc() will clear the end-of-file indicator.

Other I/O functions also affect these indicators.


Subsequent calls to fgetc() might not return EOF if the condition the caused the first EOF is removed and corresponding indicator is cleared.

like image 38
chux - Reinstate Monica Avatar answered Apr 28 '23 06:04

chux - Reinstate Monica