Search code examples
cfileeofscanffeof

losing data when reading a file with fscanf


using a part of code like this:

fscanf(f1, "%d", &n);
while(!feof(f1)){
...
fscanf(f1, "%d", &n);}

it misses the last line of the file (meeting EOF). How should I solve?

the only solution i found is:

if (fscanf(f1, "%d", &n)!=EOF){
rewind(f1);
do{
...
fscanf(f1, "%d", &n);
}while(!feof(f1));
}

Solution

  • You put fscanf at the end of the loop. fscanf reads until it is sure the number is finished. If the last character of your input file is a digit (opposed to a space or new line), when parsing last line (some people would call a line not ending in new-line "incomplete last line"), fscanf hits EOF trying to find the end of the number, so feof is true, because EOF has been hit.

    You should not check for feof, but for the return code of fscanf. It will tell you if there were some digits that could be parsed as number.

    assume your file contains "11\n23"

    f = fopen(...);
    result = fscanf(f, "%d", &i);
    // result == 1, because one variable has been read
    // i == 11, because that's the first number
    // file pointer is past the '\n', because '\n'
    //   had to be read to find out the number is not
    //   something like 110
    //   The '\n' itself has been put back using ungetc
    // feof(f) == 0, because nothing tried to read past EOF
    
    result = fscanf(f, "%d", &i);
    // result == 1, because one variable has been read by this call
    // i == 23 (obviously)
    // file pointer is at EOF (it can't go further)
    // feof(f) == 1, because fscanf tried to read past
    //   the '3' to check whether there were extra
    //   characters.
    
    //  (Your loop terminates here, because feof(f) is true
    
    result = fscanf(f, "%d", &i);
    // result == EOF (error before first variable)
    // i is likely unchanged. I am unsure whether this
    //   is guaranteed by the language definition
    // file pointer unchanged
    // feof(f) still true
    
    // You should terminate processing *NOW*, because
    // return is no longer one.