简体   繁体   中英

fscanf() stucks in an infinite loop

I've got a file containing a matrix of integers like this:

1 2 -5
0 2 4
-2 –1 3

I need to know how many elements there are in the matrix (in this case 9).

The code that calculates the number of elements is the following:

while(!feof(pFile)) {

    fscanf(pFile, "%d", &voidElement);
    elements++;
}

For some reasons, the code enters a loop when the fscanf reads the number -2 in the file containing the matrix.

Thank you for helping.

Here is a small program that looks like yours, but works (doesn't get stuck - with my input file). However you will see that it has a problem - keep reading:

#include <stdio.h>

int main(void) {
  int i, el=0;
  FILE* fp;
  fp = fopen("nine.txt","r");
  while(!feof(fp)) {
   fscanf(fp, "%d", &i);
   el++;
   printf("element %d = %d\n", el, i);
  }
  fclose(fp);
}

Output:

element 1 = 1
element 2 = 2
element 3 = -5
element 4 = 0
element 5 = 2
element 6 = 4
element 7 = -2
element 8 = -1
element 9 = 3
element 10 = 3

In other words - doing this you will get ONE MORE ELEMENT THAN YOU EXPECTED - because the feof flag is not set until you TRY TO READ PAST THE END OF THE FILE.

In other words - your method is not great; you actually should check whether the fscanf succeeded, and count those (successful reads) only.

A better technique would be:

#include <stdio.h>

int main(void) {
  int i, el=0;
  FILE* fp;
  fp = fopen("nine.txt","r");
  while(1) {
   if(fscanf(fp, "%d", &i)!=1) break;
   el++;
   printf("element %d = %d\n", el, i);
  }
  fclose(fp);
}

One more thing - if the fscanf fails for any reason (maybe there is a bad character in the file), it will never get to the end of the file and the EOF marker will never be set. This is probably why your code was actually going into an infinite loop - and why the second method (which exits the loop when fscanf did not successfully read exactly one value) will work.

EDIT when I followed the advice in my own comment below (take the input file and do a hex dump) using the numbers you had above (originally I had just typed the numbers into a text file and things worked fine…) I saw the following:

hexdump -C typedNumbers.txt 
00000000  31 20 32 20 2d 35 0a 30  20 32 20 34 0a 2d 32 20  |1 2 -5.0 2 4.-2 |
00000010  2d 31 20 33 0a                                    |-1 3.|
00000015

hexdump -C copiedNumbers.txt 
00000000  31 20 32 20 2d 35 0a 30  20 32 20 34 0a 2d 32 20  |1 2 -5.0 2 4.-2 |
00000010  e2 80 93 31 20 33 0a                              |...1 3.|
00000017

Note that the first line is identical in both files - but there are "unprintable" bytes in the second line of the second file (your original file). In particular, the bytes are

e2 80 93    before 31

instead of

2d 31

It puzzles me to see that three characters end up being represented by a single emdash - I must admit I don't understand how that is done. But there are your "bad hidden characters" as I surmised in an earlier version of my answer.

I know that there is a problem with my code (see Floris' answer ) but the main problem is that actually the minus sign before the 7th element is not a real minus sign ( - is different from , you'll notice it if you zoom in enough).

That was causing the loop to exit even before reaching the EOF (actually it had problems when the fscanf was trying to read –1 ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM