scanf忽略,无限循环

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 。 但它不等我输入一个新号码。 这是为什么?

当您输入不是数字的内容时, 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。

%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。 scanffunction – JTC1 / SC22 / WG14 – C.

因此,您应该注意scanf返回自己的通知forms以获得成功

 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。 扫描格式扫描格式不应用于交互式用户输入。 参见C FAQ 12.20

在第一个数字之后,’\ n’将在输入缓冲区中(您按下的返回数字输入),因此在第二次迭代中scanf调用将失败(因为\ n不是数字),scanf将不要从缓冲区中删除\ n,因此在下一次迭代中它将再次失败,依此类推。

您可以通过在scanf之后使用getchar()调用来读取’\ n’来解决这个问题。

由于缓冲区中存在’\ n’而出现的“答案”是错误的 – scanf("%d", ...)跳过空格,包括换行符。

如果x包含0并且scanf遇到非数字(不仅仅是空格)或EOF,它会进入无限循环,因为x将保持为0并且没有办法使它变为否则。 只需查看代码并思考在这种情况下它将做什么,就应该清楚这一点。

它进入无限循环,因为如果匹配失败,scanf()将不会使用输入令牌。 scanf()将尝试反复匹配相同的输入。 你需要刷新标准输入。

if(!scanf(“%d”,&sale.m_price))fflush(stdin);

scanf()是一个破碎的函数,使用fgets()读取行然后将结果提供给sscanf(),而我与scanf()有完全相同的问题,遗憾的是scanf()是一个非常有问题的函数来读取输入。 在我的问题中,我已经解决了无限循环问题和无效输入,如123ab

 char line[10]; while (flag==0){ printf("\nEnter Product price: "); fgets(line, 10, stdin); // read a 10 character line from standard input and store it in line array sscanf(line, "%d",&sale.m_price); // look for an integer inside line and store is in sale.m_price if (sale.m_price==0) PrintWrongInput(); else flag=1; }