【问题标题】:Can't understand this infinite loop看不懂这个无限循环
【发布时间】:2018-05-22 02:25:31
【问题描述】:

我有这段代码来读取文件,然后打印每一行,但是当我运行它时,它一直在打印 '1 ; 0; ; 0; 0; 0' 无限。 输入文件中有这个:

1 ; Visitante ; 10 ; 19 ; 2 ; 3
2 ; 1 ; Funcionario ; 8 ; 0 ; 2
3 ; 2 ; Diretor ; 12 ; 19 ; 4
4 ; Visitante ; 8 ; 0 ; 3 ; 2

代码:

#include <stdio.h>
#include <stdlib.h>


void readInput() {
   FILE * fp;
   int id = 0, acompanhantes = 0, entrada = 0, saida = 0, servico = 0;
   char tipo[256] = {};

   if ((fp = fopen("input.txt", "r")) == NULL) {
     printf("Erro a abrir o ficheiro, o programa vai terminar...\n");
     exit(1);
   }

   while ((fscanf(fp,"%d ; %d ; %s ; %d ; %d ; %d\n", &id, &acompanhantes, tipo, &entrada, &saida, &servico)) != EOF) {
     printf("%d ; %d ; %s ; %d ; %d ; %d\n", id, acompanhantes, tipo, entrada, saida, servico);
   }

   fclose(fp);

}

int main() {
  readInput();
}

【问题讨论】:

  • 我们应该假设lerInputreadInput 是同义词吗?不管怎样,看看你的台词。它们不是类型同义词,因此不能由同一组格式说明符普遍扫描这些行。 int, 字符串, 4x int, 然后 2x int, string, 3x int, 扫描失败,输入无限转换失败。
  • fscanf() 返回一个 int(匹配的项目数),因此它永远不会匹配 EOF,并且您的循环永远不会结束。
  • 您的输入与 scanf 格式不匹配。
  • @rickdenhaan EOF is 一个 int 并且fscanf 在读取任何输入之前遇到文件结尾时确实返回EOF
  • @Jocas 认为“特定格式”不匹配其中一些行,所以这是不可能的。如果您需要处理两种不同的格式,可以这样做,但需要通过fgets 进行行缓冲,然后多次调用sscanf 而不是fscanf,测试是否完全成功一路走来。

标签: c scanf


【解决方案1】:

您已点击a common gotcha of the scanf functions。如果他们无法扫描,他们只会一遍又一遍地尝试重新扫描相同的输入。

在您的情况下,文件的第一行与您的格式不匹配。

1 ; Visitante ; 10 ; 19 ; 2 ; 3
"%d ; %d ; %s ; %d ; %d ; %d\n"

所以fscanf 匹配第一列,第二列失败。它返回匹配的项目数:1。那不是EOF,所以它在同一行一遍又一遍地重复。

通常,您可以通过检查 fscanf 返回要扫描的项目总数来解决此问题。 fscanf( ... ) &gt;= 6 但这并不能解决您有一个包含不同字段的文件。

首先,我们可以通过分离读取行和解析行来解决很多潜在的问题。使用fgets + sscanf 而不是尝试同时使用fscanf。这不仅避免了无限循环,而且为我们提供了更多的解析空间。

然后我们可以读取该行一次,并尝试使用各种格式对其进行解析,直到其中一种有效为止。

char line[4096];
while (fgets( line, sizeof(line), fp) != NULL) {
    if(
        ( sscanf(line,"%d ; %d ; %s ; %d ; %d ; %d\n", &id, &acompanhantes, tipo, &entrada, &saida, &servico) >= 6 ) ||
        ( sscanf(line,"%d ; %s ; %d ; %d ; %d ; %d\n", &id, tipo, &acompanhantes, &entrada, &saida, &servico) >= 6 )
    ) {
        printf("%d ; %d ; %s ; %d ; %d ; %d\n", id, acompanhantes, tipo, entrada, saida, servico);
    }
    else {
        fprintf(stderr, "Could not parse %s.\n", line);
    }
}

【讨论】:

    猜你喜欢
    • 2021-05-17
    • 2017-10-13
    • 2014-04-10
    • 2023-03-28
    • 2016-12-14
    • 2018-03-17
    • 2023-03-10
    • 1970-01-01
    • 2017-05-16
    相关资源
    最近更新 更多