scanf失败为什么?
当我写这个,编译和运行:
int x; scanf ("%d", &x); while (x!=4) { scanf ("%d", &x); }
当插入字符或小于4的双数时,input一个无限循环。
当插入大于4的双倍时,它终止。
任何解释?
从C语言标准(n1256) :
7.19.6.2 fscanf函数
…
4 fscanf函数依次执行格式的每个指令。 如果指令失败,如下所述,函数返回。 故障被描述为input故障(由于发生编码错误或input字符不可用)或匹配故障(由于不适当的input)。
…
7作为转换规范的指令定义了一组匹配的input序列,如下所述每个说明符。 转换规范在以下步骤中执行:8input空格字符(由isspace函数指定)将被跳过,除非规范包含[ , c或n说明符。 250)
9从stream中读取input项目,除非规范包含n说明符。 input项被定义为input字符的最长序列,其不超过任何指定的字段宽度,并且是匹配input序列的或者是匹配input序列的前缀。 251)input项目保持未读状态后的第一个字符(如果有的话) 。 如果input项的长度为零,则指令的执行失败; 除非文件结束,编码错误或读取错误阻止了来自stream的input,否则这种情况是匹配失败,在这种情况下,这是input失败。
10除了%说明符的情况外,input项目(或者在%n指令的情况下,input字符的计数)被转换为适合于转换说明符的types。 如果input项目不匹配,则指令的执行失败:这种情况是匹配失败。 除非由*指示分配抑制,否则转换的结果将放置在尚未收到转换结果的format参数后面的第一个参数指向的对象中。 如果此对象没有适当的types,或者如果转换的结果不能在对象中表示,则行为是未定义的。
在第10段中增加了强调。 %d
转换说明符需要将input文本格式化为十进制整数。 如果不是,则转换失败,导致转换失败的字符将保留在inputstream中。 使用%d
转换说明符进一步调用scanf()
将会阻塞相同的字符。
scanf()
返回成功分配的数量; 你需要检查这个结果,看看转换是否成功,如下所示:
int x = 0; while (x != 4) { int result = scanf("%d", &x); if (result != 1) { printf("Last call to scanf() failed; exiting\n"); break; } }
不幸的是,在inputstream中仍然存在糟糕的input。 有一些处理这个问题的策略。 您可以使用getchar
删除违规的字符,然后重试:
while (x != 4) { int tmp; if (scanf("%d", &tmp) == 0) getchar(); else x = tmp; }
或者你可以尝试阅读下一个换行符,假设所有剩余的input是b0rked:
while (x != 4) { int tmp; if (scanf("%d", &tmp) == 0) while (getchar() != '\n') ; else x = tmp; }
或者你可以尝试读取input为文本,并使用strtol()
(我的首选技术)转换为整数:
char input[SOME_SIZE]; int x = 0; ... while (x != 4) { if (fgets(input, sizeof input, stdin)) { char *check; int tmp = (int) strtol(input, &check, 10); if (!isspace(*check) && *check != 0) { printf("%s is not a valid integer: try again\n", input); } else { x = tmp; } } else { printf("Read error on standard input\n"); break; } }
这是更多的工作,但它可以让你在分配给x
之前捕捉不好的input。
你不检查scanf
是否成功,因此你会遇到错误。 每个循环, scanf
将尝试读取和失败。
scanf
返回成功读取的项目数,因此修改循环为这样的事情while (x!=4) { if (scanf("%d",&x) != 1) break; }
while (x!=4) { if (scanf("%d",&x) != 1) break; }
当scanf停止在inputstream中的特定位置扫描时,它将永远不会前进stream,所以下一个scanf将再次尝试相同的错误…再次…并且再次
input:42 23 foo ... scanf:^ x 42 scanf:^ x 23 scanf:^ x无法使用 scanf:^ x无法使用 scanf:^ x无法使用 scanf:^ x无法使用 scanf:^ x无法使用
你传递给scanf的%d告诉它parsing一个int。 当你input一个double时,它不能parsing既不将分析的数据存储在xvariables中,因为double在32位机器上使用64位而在32位上使用int,从而产生一个Seg。 故障或随机附带影响。