Mehdi Zayene
Mehdi Zayene

Reputation: 37

fscanf - How to know if EOF means end of file or reading/another error?

I have a question about I/O in C language, how can I make a difference to know if the lecture of my file has ended or if the data can't be read (or has a problem) as in the both cases, fscanf returns EOF ?

Upvotes: 1

Views: 829

Answers (2)

anastaciu
anastaciu

Reputation: 23832

As per fscanf() return value:

ISO/IEC 9899:2017

§ 7.21.6.2 - 16 - The fscanf function returns the value of the macro EOF if an input failure occurs before the first conversion (if any) has completed. Otherwise, the function returns the number of input items assigned, which can be fewer than provided for, or even zero, in the event of an early matching failure.

EOF is a macro with the value of -1, by itself it's not distinguishable as for the reasons why it occurs.

For this distinction § 7.21.6.2 - 19 recommends the use of feof() for end-of-file and ferror() for I/O error:

EXAMPLE 3 To accept repeatedly from stdin a quantity, a unit of measure, and an item name:

#include<stdio.h> 

/*...*/

int count; floatquant; 
charunits[21],  item[21]; 

do { 
    count = fscanf(stdin, "%f%20sof%20s", &quant, units, item);
    fscanf(stdin,"%*[^\n]"); 
} while(!feof(stdin) && !ferror(stdin));

My usual approach when reading formated input, is to check the inputed values. For a sample input of 2 integers you can do something like:

int a, b;
FILE* file;
//open file to read
while(fscanf(file, "%d %d", &a, &b) == 2){ //read each 2 integers in the file, stop when condition fails, i.e. there are nothing else to read or the read input is not an integer
    //...handle inputs
}

This kind of read is safe and addresses all failure scenarios since it works for bad input and for "end of file".

Upvotes: 1

Don´t rely only on the return value of fscanf(), rely beside this one on feof() and ferror() after the call to fscanf():

FILE* file;
if((file == fopen("file.txt","r")) == NULL)
{
    fprintf(stderr, "File could not be opened!");
    return EXIT_FAILURE;
}

char buf;

/******************************************************************************/

while(fscanf(file,"%c",buf) == 1) {     // checks if an error was happen, else 
                                        // iterate to catching characters.
   /* handling of read character */
}

if(ferror(file))                        // checks if an I/O error occurred.
{
   // I/O error handling
   fprintf(stderr,"Input/Output error at reading file!");
   clearerr(file);
   // Further actions
}
else if(feof(file))                     // checks if the end of the file is reached.       
{
   // end of file handling
   fprintf(stderr,"Reached End of File!");
   clearerr(file);
   // Further actions
}

/******************************************************************************/

if(fclose(file) != 0)
{
    fprintf(stderr, "File could not be closed properly!");
    return EXIT_FAILURE;
}

Upvotes: 3

Related Questions