'Confusion with == EOF vs feof

I opened a file, the stream is found at the address of pointer ptr. I am attempting to see whether or not a file is blank. Using the following

if (fgetc(ptr) != EOF)

works as expected. When the file is blank, the statement is not executed. When the file is not blank, the statement is not executed.

However, using

if (!feof(ptr))

always executes the statement.

Why does this happen? Is there a way to use the feof function?



Solution 1:[1]

In C standard library "end of file" is not an independent self-detecting condition. "End of file" is merely a file state set by the preceding read operation. Until you perform a read operation and until that read operation bumps into the actual end of file, "eof" state is not set and feof() returns 0.

Many (most) standard I/O functions in C standard library already return some completion code that can be used to detect "end of file" condition (like fgetc() returning EOF value). This means that most of the time calling feof() is unnecessary.

In other words, if you think about "end of file" as a brick wall, in C standard library it is not sufficient to stand right in front of that wall in order to detect it. It is necessary to actually bump into that wall with your forehead in order to discover its presence.

When you open an empty file, you begin in a state "right before the wall". At this point "end of file" condition is not detected yet. You have to try reading something in order to crash into that wall and thus detect its presence.

The reasons for this design are perfectly logical. C language is designed to support various input streams and file systems, including 1) file systems that do not store file sizes at all, as well as 2) file systems that know only approximate file size (like rounded to a nearest cluster). In such file systems the end of file is usually designated by a special marker. You don't know where that marker is until you run into it while reading the file. (For the very same reason C streams do not guarantee support for positioning from SEEK_END origin in fseek function.)

As @Barmar noted in the comments, an even better example of an input stream without a pre-determined "end of file" position is standard input linked to terminal.

Solution 2:[2]

feof(f) will always return false right after you open the file because if gives you the value of a flag which is initialized to false and set to true only after at least one reading operation fails.

Solution 3:[3]

You could use feof like this:

fgetc(fp);
if (feof(fp))
  ...

feof checks an end-of-file indicator set after a read that attempted to read at or past the end of file. It is useful in situations where code that you don't control was reading from the file, and you want to stop the processing once the file has been exhausted.

Solution 4:[4]

Late answer, however to add a helpful quote from Programming in C (4th Edition) by Stephen Kochan, p. 367:

Remember, feof() tells you that an attempt has been made to read past the end of a file, which is not the same as telling you that you just read the last data item from a file. You have to read one past the last data item for feof() to return nonzero.

Italics mine.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3
Solution 4 S3DEV