fscanf()陷入无限循环

时间:2013-12-01 20:01:48

标签: c loops

我有一个包含整数矩阵的文件,如下所示:

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

我需要知道矩阵中有多少元素(在本例中为9)。

计算元素数量的代码如下:

while(!feof(pFile)) {

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

由于某些原因,当fscanf读取包含矩阵的文件中的数字-2时,代码会进入循环。

感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

这是一个看起来像你的小程序,但有效(不​​会卡住 - 使用我的输入文件)。但是你会发现它有问题 - 继续阅读:

#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);
}

输出:

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

换句话说 - 这样做你将得到比你预期更多的元素 - 因为{Miss} feof标志在你尝试阅读文件结尾之前没有设置。

换句话说 - 你的方法并不好;实际应该检查fscanf是否成功,并仅计算那些(成功读取)。

更好的技术是:

#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);
}

还有一件事 - 如果fscanf由于任何原因失败(可能文件中存在错误的字符),它将永远不会到达文件末尾并且永远不会设置EOF标记。这可能是你的代码实际上进入无限循环的原因 - 为什么第二种方法(当fscanf没有成功读取一个值时退出循环)将起作用。

编辑当我按照上面的评论中的建议(使用输入文件并执行十六进制转储)时使用上面的数字(最初我刚刚将数字输入到文本文件中)事情很好......)我看到了以下内容:

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

请注意,第一行在两个文件中都相同 - 但在第二个文件(原始文件)的第二行中有“不可打印”字节。特别是,字节是

e2 80 93    before 31

而不是

2d 31

让我感到困惑的是,看到三个角色最终被一个emdash代表 - 我必须承认我不明白这是怎么做的。但是,正如我在早期版本的答案中所推测的那样,你有“隐藏的坏人物”。

答案 1 :(得分:0)

我知道我的代码存在问题(请参阅Floris' answer)但主要问题是实际上第7个元素之前的减号不是真正的减号(-不同于,如果放大的话,你会注意到它。

这导致循环在到达EOF之前就退出了(实际上当fscanf试图阅读–1时它有问题)。