C 而依赖于扫描结果的循环过早结束
我正在用C写一个简单的程序来计算成绩和平均成绩。我通过“C 而依赖于扫描结果的循环过早结束,c,while-loop,scanf,C,While Loop,Scanf,我正在用C写一个简单的程序来计算成绩和平均成绩。我通过“xyz_output.txt”命令输出到另一个文本。输入文件中有100多行数据,但由于某种原因,程序一直在退出围绕输入第6行的循环。。。我已经检查了输入格式好几次,但我似乎不明白为什么它会过早退出。代码如下: #include <stdio.h> #include <string.h> #include <stdlib.h> int main() { char pp[4]; char s
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char pp[4];
char school[3];
int class;
int student;
int a;
int b;
int c;
int d;
int e;
int f;
int g;
int h;
int i;
int j;
int k;
int l;
int m;
int n;
int o;
int p;
int q;
int r;
float average;
int runtotal;
int grouptotal = 0;
float groupaverage;
int counter = 0;
while (scanf("%3s%2s%2i%2i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i", pp, school, &class, &student, &a, &b, &c, &d, &e, &f, &g, &h, &i, &j, &k, &l, &m, &n, &o, &p, &q, &r) == 22)
{
runtotal = (a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p+q+r);
average = (float)runtotal / 18;
grouptotal = grouptotal + runtotal;
counter++;
printf ("%i.\n", counter);
printf ("%s%s-%i-%i -- %1i %1i %1i %1i %1i %1i %1i %1i %1i %1i %1i %1i %1i %1i %1i %1i %1i %1i\n", pp, school, class, student, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r);
printf ("Total score: %i\n", runtotal);
printf ("Average: %f\n", average);
printf ("Running Total: %i\n\n", grouptotal);
}
groupaverage = (float)grouptotal / counter;
printf ("Calculations complete.\nThe total score for this group was %i.\nThe average score for this group was %f.\n", grouptotal, groupaverage);
return 0;
}
它似乎到达了“preHI5109”,但随后退出。我觉得这与我如何使用scanf有关,但我不确定我做错了什么。关于如何解决这个问题有什么建议吗?读取数据文件的方法对错误对齐、解析和I/O问题非常敏感。建议更健壮的IO和解析,因为数据文件中肯定存在一些小错误。使用
fgets()
控制读取行定向数据
char buf[100];
while (fgets(buf, sizeof buf, stdin) != NULL) {
int count = sscanf(buf, "%3s%2s%2i%2i %i %i %i %i /* ... */ %i %i",
pp, school, &class, &student, &a, &b, &c, /* ... */ &q, &r);
if (count != 22) {
printf("Error %d (TBD relevant text)\n", count);
break;
}
/* continue with normal processing */
}
其他改进inta[18]
而不是inta;INTB代码>
使用循环扫描、求和、打印18个元素。
使用“%i”
而不是“%1i”
。1
是最小宽度,为什么有它
注意:如果输入文件是由一位教授提供的,那么我就不会感到惊讶,因为其中有一些故意不好的东西。教训:除非经过充分审查,否则不要相信数据输入。用户输入是错误的。scanf
返回的数字是多少?你可以把它放在某处。。。。什么是errno
?和ferror(stdin)
?使用调试信息和所有警告(例如gcc-g-Wall
)进行编译,并使用调试器(例如gdb
)。你的操作系统和编译器是什么?也许使用%n
格式控件可能会有所帮助。我会尝试快速存储返回并返回给您。没有任何错误,程序只是退出循环并在循环结束后执行最后的计算。请看,除非这是学习C的练习,否则没有理由使用C。正如@Basile所建议的,了解scanf()
结果将有所帮助。进一步:(scanf(“%3s%2s%2i%2i%i%i%i…”与(scanf(“%3s%2s%2i%2i%i%i%i%i%i…”)相同。“%i”
之前的空格可能有助于查看,但不会影响scanf()
功能,因为“%i”
无论如何都会占用前导空格。建议使用fgets()阅读这些行。)
然后使用sscanf()
进行解析。当然,数据文件中隐藏了一些散乱的char
。谢谢chux,你的代码工作了(计数只需要22,而不是23)。我在输入文件上运行了它,它处理了所有100行数据。不过,出于学习目的,我很好奇为什么scanf会“看到”或不看到“看到”字符导致它出现故障?当用肉眼查看输入数据时,我找不到任何错误,那么scanf看到了什么而我没有看到?@Jason Sturgeon(23到22已修复)使用fgets()
一次读取一行,有利于错误定位。文本文件当然是面向行的。假设一行的末尾有额外的char
s“z”
。fgets()
将读取行(最多100行)和sscanf()
将成功扫描,忽略多余的垃圾,愉快地进入下一行。您的原始代码将尝试将z
读为pp
,这将导致厄运。最终,%i
将尝试扫描字母失败,并且不会继续进行。但在出现原始问题的地方,情况有点混乱。@Ja顺便说一句,为了提高效率,使用sscanf()
工具:int ch;sscanf(buf,“%3s%2s%2i…%i%i%c”
。通过添加“%c”
,并且不增加22到23,您已经创建了句子。在上一次预期的int
之后的任何非空格都会被检测到。(我在最初的回答中,有1/2个实现了这一点。)再次感谢chux。我实际上是一名语言学教授,所以编程远不是我的专长,但我涉足C主要是因为我听说大多数其他语言都是基于C语言的,如果你能用C语言编写代码,那么转换到其他语言就容易得多。用它来整理一些简单的数学问题研究似乎是一个很好的起点,也是一种在未来为自己节省数小时时间的方法。谢谢你幽默地回答我的问题。到时候我会让你的专业人士回到这一点上。
char buf[100];
while (fgets(buf, sizeof buf, stdin) != NULL) {
int count = sscanf(buf, "%3s%2s%2i%2i %i %i %i %i /* ... */ %i %i",
pp, school, &class, &student, &a, &b, &c, /* ... */ &q, &r);
if (count != 22) {
printf("Error %d (TBD relevant text)\n", count);
break;
}
/* continue with normal processing */
}