为什么我不能在错误后使用fscanf阅读?

时间:2016-06-16 13:06:56

标签: c scanf

我正在从文件中读取信息。该文件包含格式

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

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

2 个答案:

答案 0 :(得分: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
    }
}

答案 1 :(得分:1)

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

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

strtol()有原型

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

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

如果*str != '\0'*endptr == '\0',转化成功。