int flag = 0;
int price = 0;
while (flag==0)
{
printf("\nEnter Product price: ");
scanf("%d",&price);
if (price==0)
printf("input not valid\n");
else
flag=1;
}
当我输入有效数字时,循环按预期结束。但是如果我输入一些不是数字的东西,比如hello
,那么代码会进入无限循环。它只是保持打印Enter Product price:
和input not valid
。但它不等我输入一个新号码。那是为什么?
答案 0 :(得分:4)
当您输入不是数字的内容时,scanf
将失败并将这些字符留在输入中。因此,如果您输入hello
,则scanf将看到h
,拒绝它对十进制数无效,并将其保留在输入上。下一次循环,scanf
将再次看到h
,因此它会一直循环播放。
此问题的一个解决方案是使用fgets
读取整行输入,然后使用sscanf
解析该行。这样,如果sscanf
失败,则输入中不会留下任何内容。用户必须输入fgets
的新行才能阅读。
这些方面的东西:
char buffer[STRING_SIZE];
...
while(...) {
...
fgets(buffer, STRING_SIZE, stdin);
if ( sscanf(buffer, "%d", &price) == 1 )
break; // sscanf succeeded, end the loop
...
}
如果您只是按照另一个答案中的建议执行getchar
,那么您可能会错过\n
字符,以防用户在数字后面输入内容(例如空格,可能后跟其他字符)
您应该始终测试sscanf
的返回值。它返回分配的转换次数,因此如果返回值与请求的转换次数不同,则表示解析失败。在此示例中,请求了1次转换,因此sscanf
在成功时返回1。
答案 1 :(得分:3)
%d格式用于小数。当scanf失败时(输入其他小数),导致失败的字符将保留为输入。
实施例
int va;
scanf("%d",&va);
printf("Val %d 1 \n", val);
scanf("%d",&va);
printf("Val %d 2 \n", val);
return 0;
因此不会发生转换。
如果之前发生输入故障,scanf函数将返回宏EOF的值 任何转换。否则,scanf函数返回输入项的数量 分配,在早期的情况下,可以少于提供的,甚至为零 匹配失败
<子> 7.19.6. The scanf function - JTC1/SC22/WG14 - C 子>
因此,您应该注意scanf
返回自己的成功通知形式
int scanf(char *format)
所以你也可以做以下
do {
printf("Enter Product \n");
}
while (scanf("%d", &sale.m_price) == 1);
if(scanf("%d", &sale.m_price) == 0)
PrintWrongInput();
还要保持在脑后,尽量远离scanf。 scanf或扫描格式化不应用于交互式用户输入。 See the C FAQ 12.20
答案 2 :(得分:1)
在第一个数字之后,'\ n'将在输入缓冲区中(您按下的返回数字输入),因此在第二次迭代中scanf调用将失败(因为\ n不是数字) ,scanf不会从缓冲区中删除\ n,因此在下一次迭代中它将再次失败,依此类推。
你可以通过在scanf之后用getchar()调用来读取'\ n'来解决这个问题。
答案 3 :(得分:1)
因为缓冲区中有'\ n'而错误的“答案”是错误的 - scanf("%d", ...)
会跳过空格,包括换行符。
如果x
包含0且scanf
遇到非数字(不仅仅是空格)或EOF,它将进入无限循环,因为x
将保持为0并且无法使用它否则。通过查看代码并考虑在这种情况下它将做什么,这应该是清楚的。
答案 4 :(得分:0)
它进入无限循环,因为如果匹配失败,scanf()将不会使用输入令牌。 scanf()将尝试反复匹配相同的输入。你需要冲洗标准输入。
if(!scanf(“%d”,&amp; sale.m_price)) fflush(标准输入);
答案 5 :(得分:0)
编辑:当我第一次写这个答案的时候,我对scanf()
的工作方式非常愚蠢和无知。
scanf()
不是一个破碎的功能,如果我不知道scanf()
是如何工作的,我不知道如何使用它,那么我可能是避风港请阅读scans()
的手册,但这不是scanf()
的错误。scanf()
的工作原理。当您在代码中使用scanf("%d", &price)
时,scanf()
会尝试从输入中读取integer
,但如果输入非数字值,则scanf()
知道它不是正确的数据类型,所以它在下一个循环周期将读取输入放回缓冲区,但是无效输入仍然在缓冲区中,这将导致scanf()
再次失败,因为缓冲区没有'被清空了,这个循环一直持续着。
为了解决这个问题,您可以使用scanf()
的返回值,这将是读取的成功输入的数量,但是您需要通过刷新缓冲区来丢弃无效输入以避免无限循环,当按下enter
键时刷新输入缓冲区,您可以使用getchar()
功能暂停获取输入,这需要您按下enter
因此,丢弃无效输入,请注意,无论您输入的数据类型是否正确,都不会按enter
键两次,因为newline character
仍然在缓冲区中。在scanf()
成功完成从输入中读取integer
之后,它会将\n
放回缓冲区,因此getchar()
会读取它,但由于您不需要它,丢弃它是安全的:
#include <stdio.h>
int main(void)
{
int flag = 0;
int price = 0;
int status = 0;
while (flag == 0 && status != 1)
{
printf("\nEnter Product price: ");
status = scanf("%d", &price);
getchar();
if (price == 0)
printf("input not valid\n");
else
flag = 1;
}
return 0;
}