Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

fscanf reads the last integer twice

Tags:

c

file-io

I have the following simple program to read from a text file (num.txt). The text file has numbers 1 2 3 4 5 in each line. When I run the program, it prints 5 twice. Can anybody tell me why is this happening, and how to fix it? thanks in advance

int main(void)
{
   int number;
   FILE *file;

   int i = 0;;

   file = fopen("num.txt", "r");

   while (!feof(file)){

      fscanf(file, "%d", &number);
      printf("%d\n", number);
      }

   return 0;
}

Here's my text file num.xtx

1
2
3
4
5

And here's the program output

1
2
3
4
5
5

There is an extra 5

like image 987
pdhimal1 Avatar asked Apr 20 '14 17:04

pdhimal1


People also ask

Does fscanf only read one line at a time?

This means that even a tab ( \t ) in the format string can match a single space character in the input stream. Each call to fscanf() reads one line from the file.

What does fscanf() do?

The fscanf() function reads data from the current position of the specified stream into the locations that are given by the entries in argument-list, if any. Each entry in argument-list must be a pointer to a variable with a type that corresponds to a type specifier in format-string.

What does fscanf return if the end of the file was reached?

fscanf returns EOF if end of file (or an input error) occurs before any values are stored. If values are stored, it returns the number of items stored; that is, the number of times a value is assigned with one of the fscanf argument pointers.


2 Answers

From the man page of scanf family of functions,

The value EOF is returned if the end of input is reached before either the first successful conversion or a matching failure occurs. EOF is also returned if a read error occurs, in which case the error indicator for the stream is set, and errno is set to indicate the error.

This means that the last successful fscanf call reads the last line from the stream file after which the while loop condition !feof(file) is true because the end of file condition is not met yet. This means the loop is executed one extra time and the previous value of the variable number is printed again.

Please read this - while(!feof(file)) is always wrong

You should check the return value of scanf instead of checking the end of file indicator on the file stream.

#include <stdio.h>   

int main(void) {
   int number;
   FILE *file = fopen("num.txt", "r");

   // check file for NULL in case there
   // is error in opening the file
   if(file == NULL) {
      printf("error in opening file\n");
      return 1;
   }      

   // check if fscanf call is successful 
   // by checking its return value for 1.
   // fscanf returns the number of input
   // items successfully matched and assigned
   while(fscanf(file, "%d", &number) == 1)
      printf("%d\n", number);

   return 0;
}
like image 166
ajay Avatar answered Oct 07 '22 12:10

ajay


The second time fscanf failed and didn't write anything to number, that's why it's still 5 from the last time. To know if fscanf succeeded, you have to check its return value.

fscanf returns the number of arguments that it wrote. In your case, if it returns 1, it worked; if it returns 0, it didn't. This is what you should check instead of feof.

while (fscanf(file, "%d", &number) == 1)
{
    printf("%d\n", number);
}
like image 31
zneak Avatar answered Oct 07 '22 12:10

zneak