下面是我输入数字并打印它的简单代码。它在while(1)循环内,所以我需要“输入数字无限次数 - 每次打印数字并再次等待输入”。
#include<stdio.h>
int main()
{
int i;
while(1){
printf("\nenter i \n");
scanf("%d", &i);
if(i==1)
{
printf("%d \n", i);
}
}
return 0;
}
它工作正常。但突然我注意到如果我输入一个字符(例如:“w”)而不是数字,从那里它不会要求输入!!! **
它继续打印,
enter i
1
enter i
1
......
当我使用GDB进行调试时,我注意到在输入“w”后,字符“w”的值不存储在&amp; i中。在我输入“w”之前,它有0x00000001,因此在整个过程中打印出“1”。
为什么不要求其他输入?根据我的知识,当我输入“w”时,“w”的ascii值应存储在&amp; i中。但它不会发生。
如果我在while
循环中放置“int i;”它可以正常工作!为什么呢?
请按以下方式测试我的代码:
答案 0 :(得分:3)
您还需要检查scanf
的返回值,因为它将返回成功扫描和解析的值的数量。如果它返回零(或EOF
),那么你应该退出循环。
当您输入例如字符'w'
而不是数字是scanf
函数将在扫描和解析时失败,并返回零。但是输入不会从输入缓冲区中删除(因为它没有被读取),所以在下一个循环scanf
将再次读取非数字输入并失败,它将无限地执行此操作。
答案 1 :(得分:3)
scanf
格式说明符的 %d
将读取&#34;看起来像数字&#34;的所有内容,即满足严格定义的整数十进制表示格式:一些可选的空格后跟一个可选的符号,后跟一系列数字。一旦遇到一个不可能是十进制表示的一部分的字符,scanf
就会停止读取并使输入流中的其余输入数据保持不变(等待下一个scanf
)。如果您只输入w
,则scanf
将找不到任何&#34;看起来像数字&#34;。它什么都不读。相反,它会通过返回值报告失败。同时,您的w
将保留在输入流中,未读。下次您尝试scanf
时,会再次发生同样的事情。再次,一次又一次...... w
将永远位于输入流中,导致您的每个scanf
调用立即失败,并且您的循环将永远运行(除非您的未初始化变量{ {1}}纯粹的机会恰好以i
的价值开始其生命。)
您认为输入1
会使w
读取scanf
的ASCII码完全不正确。这听起来接近w
格式说明符会做什么,但这甚至不接近%c
格式说明符所做的。 %d
不会将任意字符读为ASCII码。
另请注意,每当您尝试在输入流中调用%d
并scanf
时,您的w
都会失败并保留scanf
的值不变。如果您在循环中声明了i
,那么i
的值在每次尝试失败i
后都将保持未初始化且不可预测。在这种情况下,程序的行为是不确定的。它甚至可能产生一种“工作正常”的错觉。 (在这种情况下你可能理解的任何事情)。
答案 2 :(得分:3)
您可以尝试以下解决方法:
int main()
{
int i;
char c;
while (1)
{
printf("enter i: ");
if (scanf("%d",&i) == 0)
scanf("%c",&c); // catch an erroneous input
else
printf("%d\n",i);
}
return 0;
}
顺便说一下,你什么时候计划break
从那个(目前是无限的)循环?
答案 3 :(得分:2)
你需要read up on scanf()
,因为你的计划似乎是基于一些错误的假设。
它不会解析字符,因为转换格式说明符%d
表示&#34;十进制整数&#34;。
另外,请注意必须检查返回值,因为I / O可能会失败。当您输入与转换说明符不匹配的内容时,scanf()
无法解析它。
使用fgets()
,然后使用例如阅读整行可能会更好sscanf()
来解析这一行。通过这种方式获得强大的输入读取要容易得多。
答案 4 :(得分:1)
scanf
返回类型,并根据输入可以使用getchar
来解决您的问题。
示例代码
int main()
{
int i;
int ch;
while(1){
printf("\nenter i \n");
if ( scanf("%d", &i) !=1 )
{
/*consume the non-numeric characters*/
for (; (ch = getchar()) != EOF && ch != '\n'; ) { }
}
if(i==1)
{
printf("%d \n", i);
}
}
return 0;
}
说明强>
当scanf(&#34;%d&#34;,&amp; i)遇到该字符时,它将无法读取该字符。该字符仍将保留在输入流中。因此,要使用这些字符,可以使用getchar()
。然后scanf
将在进一步迭代中等待下一个输入。