0

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.

siannone
  • 6,617
  • 15
  • 59
  • 89
  • 2
    Did you even see the list of similar questions on SO, before click "Post Your Question" button ? If not, see your right hand corner now – P0W Dec 01 '13 at 20:04
  • I read them but they're not having my same problem. Can you point me to the answer you think has the solution? – siannone Dec 01 '13 at 20:09
  • first read [this](http://stackoverflow.com/q/5431941/1870232) and then probably [this](http://stackoverflow.com/q/17921514/1870232) – P0W Dec 01 '13 at 20:15
  • Found why it was stuck in a loop. Look at [my answer](http://stackoverflow.com/a/20318700/365630) if you're interested. – siannone Dec 01 '13 at 23:46

2 Answers2

2

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.

Floris
  • 45,857
  • 6
  • 70
  • 122
  • I got what you mean, but now the problem is that it stops reading after it reads the 7th element (`-2`) while before it was looping on `-2`. – siannone Dec 01 '13 at 21:09
  • Why doesn't it keep reading until the 9th element? My output is exactly the same as yours but it ends at the 7th element :S – siannone Dec 01 '13 at 21:15
  • 1
    It stops when there is an error converting the next number. If it reads `-2` correctly, then your `-1` isn't what you think it is. Could it be that you have an `emdash` or that it's a lower case `l` (that is lower case L) and not the number `1`? Can you do a hex dump of the characters in your file to see what they are? Any hidden characters? – Floris Dec 01 '13 at 21:32
  • -1: except it doesn't work -- you're using `while(!feof(..` which is pretty much always wrong, doing an extra iteration of the loop. Use `while(fscanf(..) > 0)` instead. – Chris Dodd Dec 01 '13 at 22:31
  • Ok, my code wasn't very good but in a way or another i would have found the reason why it wasn't working. Actually the REAL problem was that my teacher gave me a file where the minus sign before the `1` wasn't really a minus sign but something else and that was causing the cycle to end at the 7th element :| P.S. If you look closely at the matrix in the question you can see that the damn minus sign is slightly different from a normal minus sign. – siannone Dec 01 '13 at 23:34
  • @chrisdodd if you had read all the way through you would have seen that the first code snippet explains what is wrong and the second doesn't do `while(feof)`. So I'm not sure it deserves a downvote (especially since I suggested in the comment to check that the minus sign was in fact a minus sign... Which it was not). – Floris Dec 02 '13 at 00:12
  • 1
    donwnvote removed, as you edited the answer to highlight the problem with `feof` – Chris Dodd Dec 06 '13 at 18:19
  • @ChrisDodd thanks. After I read your comment I re-read my answer and recognized how the first part could be misinterpreted - so I edited to make the point more emphatically. This is how downvoting (and reversing downvotes) is supposed to work. Cheers! – Floris Dec 06 '13 at 18:26
0

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).

Community
  • 1
  • 1
siannone
  • 6,617
  • 15
  • 59
  • 89
  • That was actually what I suggested in my comment!... An `emdash` looks like a minus sign but is wider. – Floris Dec 02 '13 at 00:10
  • 1
    Yup, that's why i put a +1 on your comment :) And since you added informations about the problem i also marked your reply as the answer because it's way better than mine. – siannone Dec 02 '13 at 08:57