Test the I/O operations themselves; don't use feof()
unless you're writing Pascal (and C is not Pascal!)
#include <stdio.h>
int main(void)
{
FILE *f = fopen("book2.txt", "r");
char a[200];
if (f != 0)
{
while (fscanf(f, "%199s", a) == 1)
{
printf("%s ", a);
printf("%ld\n", ftell(f));
}
putchar('\n');
fclose(f);
}
return 0;
}
Note that the revised code tests f
before using it, and protects against buffer overflow by specifying how long the string is in the conversion specification. Be aware that %s
reads up to a white space character; it does not read lines unless there is no white space on each line.
You use feof()
to distinguish between a conversion failure, an I/O error and EOF after an operation such as fscanf()
reports trouble. For example:
#include <stdio.h>
int main(void)
{
FILE *f = fopen("book2.txt", "r");
char a[200];
if (f != 0)
{
while (fscanf(f, "%199s", a) == 1)
{
printf("%s ",a);
printf("%ld\n", ftell(f));
}
putchar('\n');
if (feof(f))
printf("EOF\n");
else if (ferror(f))
printf("I/O error\n");
else
printf("Conversion failed\n");
fclose(f);
}
return 0;
}
With %s
, you won't get to conversion failed, and I/O error is pretty improbable too. If the conversion specifier was %d
, though, a punctuation character in the data could land you with 'Conversion failed'.
In over 25 years worth of C coding, I've got 2 places in my code that use feof()
out of thousands of files (I did a check a few months ago), and in both cases, the code is distinguishing between EOF and error (roughly as shown).