如果scanf遇到不匹配,我想给出错误消息然后继续读取其余输入。如果其中一个输入格式不正确,我当前的代码将进入无限循环。
预期输入:
101,Betty,Hay,123 Main St.,23
234,Sheila,Benn,937 Ash Ave.,46
384,Ron,Jewell,3991 Cedar Ave.,30
291,Bill,Read,83 Crescent St.,19
103,Alexander,Ott,100 2nd St.,21
115,Tricia,Munson,585 Oxen Ave.,28
118,Sam,Munson,585 Oxen Ave.,35
110,Valerie,Parker,1513 Copper Rd.,37
代码:
#include <stdio.h>
int main()
{
int sum = 0;
int count = 0;
while (1)
{
int id;
char first[80], last[80], addr[80];
int age;
scanf("%d,%80[^,],%80[^,],%80[^,],%d", &id, first, last, addr, &age);
if (feof(stdin)) break;
printf("id=%d first=%s last=%s addr=%s age=%d\n",
id, first, last, addr, age);
sum += age;
count++;
}
printf("Average age is %f\n", (float)sum / count);
return 0;
}
我尝试通过将scanf放在if语句中将其与预期的读取次数进行比较来解决这个问题,这有助于显示错误消息,但无助于读取其余的输入。有没有办法跳到下一行输入?
答案 0 :(得分:2)
您需要直接从scanf()
测试结果。在此上下文(以及大多数其他内容)中,我建议您使用fgets()
和sscanf()
而不是普通scanf()
。
#include <stdio.h>
int main(void)
{
int sum = 0;
int count = 0;
int lineno = 0;
char line[4096];
while (fgets(line, sizeof(line), stdin) != 0)
{
int id;
char first[80], last[80], addr[80];
int age;
lineno++;
if (sscanf(line, "%d,%79[^,],%79[^,],%79[^,],%d", &id, first, last, addr, &age) != 5)
fprintf(stderr, "Invalid data in line %d:\n%s", lineno, line);
else
{
printf("id=%d first=%s last=%s addr=%s age=%d\n",
id, first, last, addr, age);
sum += age;
count++;
}
}
printf("Average age is %f\n", (float)sum / count);
return 0;
}
其中的修复包括:
fgets()
) - 使用feof()
通常不合适。sscanf()
调用是否找到5个值。sscanf()
等需要在结尾处排除空字节的大小 - 因此格式为80到79的变化。scanf()
代替了它,它已经选择了行的一个不确定的初始部分,留下谁知道剩下哪些报告错误。在这里,您获得了整条线,并且可以更有意义地报告错误。我添加了一个行号来进一步改进。答案 1 :(得分:1)
当scanf()
无法阅读时,它会在失败的地方停止。你需要忽略其余部分。
一种方法是逐个阅读字符,直到看到换行符。您可以使用getc()
功能。您也可以使用fgets()一次性读取其余内容。然后使用scanf()
继续。
答案 2 :(得分:1)
出于这个原因,使用scanf
不是最佳选择。我建议使用fgets
将stdin
中的整行文本捕获到您的角色数组中。然后使用strtok
标记字符串并处理每个输入。
也许是这样的:
#include <stdio.h>
#include <string.h>
int main()
{
int sum = 0;
int count = 0;
while (1)
{
int id;
char line[240], * token;
char first[80], last[80], addr[80];
int age;
if (fgets(line,240,stdin) == NULL) break;
line[strlen(line) - 1] = '\0'; /* remove \n */
id = atoi(strtok(line,","));
strcpy(first,strtok(NULL,","));
strcpy(last,strtok(NULL,","));
strcpy(addr,strtok(NULL,","));
age = atoi(strtok(NULL,","));
printf("id=%d first=%s last=%s addr=%s age=%d\n",
id,first, last, addr, age);
sum += age;
count++;
}
printf("Average age is %f\n", (float)sum / count);
return 0;
}