Monday 30 January 2017

c - What is the better way to check EOF and error of fgetc()?




I always use this approach




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


As it seems to me more readable and robust. But to an answer of mine link, chux commented that





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




As



    while(1)
{
c = fgetc(fp);

if ( feof(fp) )
{
break ;
}
printf("%c", c);
}


is more robust than the first version. So what version should I use? Please explain me why that version is better.




EDIT



In question Why is “while ( !feof (file) )” always wrong? there asked why feof() in control loop always wrong. But checking feof() in if condition in proper way is always wrong? Explanation is appreciable.


Answer



I usually program input loops like this:



int c;

while (c = fgetc(fp), c != EOF) {
/* do something with c here */

}

/* check if EOF came from an end-of-file or an error */
if (ferror(fp)) {
/* error handling here */
}


You should generally not use a loop condition like this:




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


or



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

break;
}


Because this breaks when an IO error is encountered. In this case, fgetc returns EOF but the end-of-file flag is not set. Your code could enter an infinite loop as an error condition usually persists until external action is taken.



The proper way is to check the result of fgetc(): If it's equal to EOF, you can usually stop reading further data as both in case of an IO error and an end-of-file condition, it's usually not possible to read further data. You should then check if an error occurred and take appropriate action.


No comments:

Post a Comment

c++ - Does curly brackets matter for empty constructor?

Those brackets declare an empty, inline constructor. In that case, with them, the constructor does exist, it merely does nothing more than t...