如果我先前输入了某个输入,为什么scanf()不等待下一个输入

时间:2014-08-26 08:33:37

标签: c while-loop scanf infinite-loop

下面是我输入数字并打印它的简单代码。它在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”。

  1. 为什么不要求其他输入?根据我的知识,当我输入“w”时,“w”的ascii值应存储在&amp; i中。但它不会发生。

  2. 如果我在while循环中放置“int i;”它可以正常工作!为什么呢?

  3. 请按以下方式测试我的代码:

    • 复制并粘贴并运行
    • 当“输入i”提示将进入1
    • 第二次输入“w”。看看会发生什么......

5 个答案:

答案 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码。

另请注意,每当您尝试在输入流中调用%dscanf时,您的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将在进一步迭代中等待下一个输入。