What is the best way to check EOF and fgetc () error?

I always use this approach

int c; while ((c = fgetc(fp))!=EOF) { printf("%c", c); } 

It seems to me more readable and reliable. But in my answer link , chux commented that

if (feof (fp)) is more stable than int c; while ((c = fgetc (fp))! = EOF)

how

  while(1) { c = fgetc(fp); if ( feof(fp) ) { break ; } printf("%c", c); } 

more reliable than the first version. So which version should I use? Please explain to me why this version is better.

EDIT

In the question, Why is "while (! Feof (file))" always wrong? "They asked why feof () in the control loop is always wrong. But check feof() if the condition is properly always incorrect? The explanation is noteworthy.

+7
c fgetc
source share
3 answers

I usually program input loops as follows:

 int c; while ((c = fgetc(fp)) != EOF) { /* do something with c here */ } /* check if EOF came from an end-of-file or an error */ if (ferror(fp)) { /* error handling here */ } 

Normally you should not use a loop condition, for example:

 while (!feof(fp)) { /* do stuff */ } 

or

 for (;;) { c = fgetc(fp); if (feof(fp)) break; } 

Since this is interrupted when an I / O error occurs. In this case, fgetc returns EOF , but the end-of-file flag is not set. Your code may go into an infinite loop, because the error condition usually persists until an external action is performed.

The correct way is to check the result of fgetc() : if it is EOF , you can usually stop reading additional data, both in the case of an I / O error and in the end-of-file state, it is usually impossible to read further data. Then you should check if an error has occurred and take appropriate action.

+4
source share

The problem of testing the error state arose due to a regional case in C.

fgetc() returns an int . Its values ​​are in the range of unsigned char and EOF , (some negative number).

 int ch; while ((ch = fgetc(fp)) != EOF) { // do something with ch } if (ferror(fp)) Handle_InputError(); if (feof(fp)) Handle_EndOffFile(); // Usually nothing special 

However, C allows unsigned char have a wider range than a positive int number. Converting a unsigned char to int has a specific implementation behavior, which can lead to the conversion of the unsigned char value to a negative int - and the value corresponding to EOF .

Such platforms are rare, but not in the mainstream of 2015. Most of them will have UCHAR_MAX <= INT_MAX , and this style is commonly used. It is doubtful that these platforms will become commonplace due to the amount of code, as above, which relies on EOF other than unsigned char converted to int .

If the code should handle the rare case when UCHAR_MAX > INT_MAX , then

 int c; for (;;) { c = fgetc(file); if (c == EOF) { if (feof(file)) break; if (ferror(file)) break; // fall through if both if fail. } // do stuff with c } 

A popular link in while (! Feof (file)) is always incorrect? emphasizes that the error code is often made using the results of fgetc(in) before checking for problems. Both of the above codes check the error conditions before using the result of fgetc() .


The second code handles all situations, including those that can only be applied to a computer sitting in some long-forgotten garbage heap. The first is much more common.

+4
source share

The proposed improvement is no better, even less reliable.

As explained here , it enters an infinite loop if a read error occurs (without eof). In this case, feof will return 0 , and fgetc will return EOF .

Your version does not have this problem.

In addition, your version is shorter, less complex, and fairly standard.

+1
source share

All Articles