tomashauser
tomashauser

Reputation: 571

How do you differentiate between the end of file and an error using fscanf() in C?

According to manual, int fscanf(FILE *stream, const char *format, ...) returns the number of input items successfully matched and assigned, which can be fewer than provided for, or even zero in the event of an early matching failure. How shall I differentiate between:

Upvotes: 1

Views: 525

Answers (1)

Jonathan Leffler
Jonathan Leffler

Reputation: 753615

See the 'return values' section of the POSIX specification for fscanf(), for example.

  • Zero matched and assigned items is reported by fscanf() returning 0.

  • End of file is reported by fscanf() returning EOF.

  • An empty file is reported by the first call to fscanf() returning EOF.

Note that the prescription makes it difficult to spot the difference between an empty file (no bytes) and a file with no useful data in it. Consider this test program (I called it eof59.c, compiled to create eof59):

#include <stdio.h>

int main(void)
{
    char buffer[256];
    int rc;

    while ((rc = scanf("%255s", buffer)) != EOF)
        printf("%d: %s\n", rc, buffer);
}

If you run it with /dev/null as input (the ultimate empty file), it says nothing. However, it also says nothing if you feed it a file with a single blank (and no newline), or just a newline, or indeed any sequence of white space. You can also experiment replace the format string with " x %255s". Feeding it a file with just an x (possibly with white space around it) generates no output. Feed it a file with a y as the first character (other than white space) and the program runs for a long time reporting 0: on each line of output.

Note that while (!feof(file)) is always wrong, but after a function such as scanf() has returned EOF, you can legitimately use feof() and ferror() to disambiguate between genuine EOF and an error on the file stream (such as a disk crashing or …).

if (feof(stdin))
    printf("EOF on standard input\n");
if (ferror(stdin))
    printf("Error on standard input\n");

With the code shown, you should normally see 'EOF on standard input'; it would probably be quite hard to generate (even simulate) an error on standard input. You should not see both messages, and you should always see one of the messages.

Upvotes: 5

Related Questions