【问题标题】:Why cant I read using fscanf after an error?为什么我在出错后无法使用 fscanf 读取?
【发布时间】:2016-06-16 13:06:55
【问题描述】:

我正在从文件中读取信息。该文件由格式组成

5
3 4 5 6
5 6 a 8 9 2
3 9 42 51 32
67 53 43
5 6 7 8 9 2

第 1 行包含 N 个测试用例 接下来的 N 行将包含由空格分隔的整数。 现在我想要的输出是

18
Invalid Input
137
163
37

对于每个测试用例,输出由一个对应于加法的整数组成。 我已经给出了代码

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

int main()
{
   FILE *fp;
   int flag=0,total=0,r=0,n,i,value,x;
   char filename[100],c;
   scanf("%s",filename);
   fp=fopen(filename,"r");
   fscanf(fp,"%d",&n);
   for(i=1;i<=n;i++)
   {
       total=0;
       flag=0;
       do
    {
        r=fscanf(fp,"%d%c",&value,&c);
        if(r!=2)
        {
            printf("\nInvalid Input");
            flag=1;
            break;
        }
        else
            total+=value;
    }while(c!='\n');
    if(flag!=1)
    {
       printf("\n%d",total);
    }
}
}

但是由于我们在出错后无法使用 fscanf 读取,所以我无法读取整个输入。而且我得到了输出

18
Invalid Input
Invalid Input
Invalid Input
Invalid Input

那么我该怎么做才能获得所需的输出

【问题讨论】:

  • 不匹配的字符会一直保留在输入流中,直到被读取。由于您只读取数字,因此您永远不会从输入流中删除它。您可以使用getchar 读取一个字符,然后重试see here
  • 我试过了,但我使用的是 fscanf 但不是 scanf。它不工作。请帮助我
  • 您可以将 fscanf 与 %c 一起使用,如下面的答案所示,或者 fread(fp, dummy, 1)

标签: c scanf


【解决方案1】:

scanf 到达带有无效字符'a' 的位置时,它会尝试使用%d 格式说明符读取它。由于这不起作用,scanf'a' 留在缓冲区中,并返回 0 以表示从输入中读取的项目数。

由于您的代码再次尝试读取%d,因此什么也没有发生:缓冲区保持在读取之前的位置,'a' 作为下一个字符。这一直持续到计数 n 用完为止。

通过添加从输入中读取的代码来解决此问题,直到退出内部循环后到达'\n'EOF

do {
    ... // This is your reading loop
} while (c != '\n');
// We can reach this line either because `c` is `'\n'`, or because of an error
// If we are here due to an error, read until the next `'\n'`
while (c != '\n') {
    if (fscanf(fp, "%c", &c) == 0) {
        break; // We are at the end of file
    }
}

【讨论】:

    【解决方案2】:

    由于您的输入可能包含整数以外的内容,因此理想情况下您应该读取字符(或者更确切地说是字符数组、字符串)。然后您尝试将这些转换为整数并报告任何转换错误。

    从字符串到整数 (long) 的转换可以使用在 stdlib.h 中定义的 strtol() 完成。还有一个更容易使用的atoi() 函数,但它没有提供任何检查转换是否成功的方法。

    strtol() 有原型

     long strtol(const char *restrict str, char **restrict endptr, int base);
    

    str 是你的字符串,base 是基数 (duh),即 10,endptr 是指向 char 的指针,例程将设置为第一个字符 没有转换。

    如果*str != '\0'*endptr == '\0' 则转换成功。

    【讨论】:

      猜你喜欢
      • 2013-05-04
      • 2022-01-01
      • 1970-01-01
      • 2016-03-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多