For example this data file abc.txt
abc
Note that there is no newline at the bottom.
When I write the following program in C
#include <stdio.h>
int main(){
FILE *fp = fopen("abc.txt","rb"); // NOTE this is "rb"
while (!feof(fp)){
fprintf(stdout, "%c", fgetc(fp));
fprintf(stdout, "%d", feof(fp));
}
fclose(fp);
return 0;
}
The stdout result is like this:
[xxx@xxx hello]$ ./a.out
a0b0c0
0�1[xxx@xxx hello]$
What is the additional output bytes in the last line?
feof
reports whether the EOF indicator has been set, and it's set when you try to read past the end of the file. So the final fgetc
reads past the end of the file, returns EOF
(typically -1), and then feof
returns 1.
This is made more clear if you use %d
rather than %c
to show the result of fgetc
:
#include <stdio.h>
int main(){
FILE *fp = fopen("abc.txt","rb"); // NOTE this is "rb"
while (!feof(fp)){
fprintf(stdout, "%d:", fgetc(fp));
fprintf(stdout, "%d\n", feof(fp));
}
fclose(fp);
return 0;
}
Output:
97:0
98:0
99:0
-1:1
I'd probably write the code avoiding feof
, and use that fgetc
returns EOF when there's an error or the end of the file has been reached.
#include <stdio.h>
int main(){
FILE *fp = fopen("abc.txt","rb"); // NOTE this is "rb"
while (1) {
int c = fgetc(fp);
if (c == EOF) break;
printf("%c", c);
}
fclose(fp);
return 0;
}
Note that this code is still flawed because it treats errors like EOF: you should check if there was a read error using ferror
.