为啥这个 Scanf 会导致无限循环?

Posted

技术标签:

【中文标题】为啥这个 Scanf 会导致无限循环?【英文标题】:Why Does This Scanf Result in Infinite Loop?为什么这个 Scanf 会导致无限循环? 【发布时间】:2012-09-27 20:23:44 【问题描述】:

所以我刚刚开始为我的一个班级学习 C,我一直在做这个作业,但这部分让我感到困惑。我有一些基本上看起来像这样的代码:

#include <stdio.h>
#include <string.h>

int main(void)

    int one = 0;
    int two = 0;
    char oneWord[100]; 
    char twoWord[100];

    printf("Enter a two digit number: ");
    scanf("%d%d", &one, &two);

    strcpy(firstWord, "Test");
    strcpy(secondWord, "Two");

    printf("%s", firstWord);

    return 0;

现在,撇开程序的逻辑/目的不谈,我无法弄清楚为什么该 scanf 语句会导致无限循环?当我将其注释掉并且最终的printf 语句运行良好时,我确定这就是问题的原因。

我尝试将其更改为 scanf("%d,%d", %one, %two),当我在输入中添加逗号时,这似乎工作正常。但我希望能够取一个像 55 这样的数字并将其分成 2 位数字。我到底做错了什么?

【问题讨论】:

抱歉,我没有阅读完整的故事。将%d 更改为%c 以仅读取一个字符 大声笑,在发布问题后才发现这一点。就我而言,有效的是scanf("%1d%1d", &amp;one, &amp;two) 输入的数字用空格隔开怎么样? 【参考方案1】:

我可能错了,但%d 的意思是“一个整数”,而不是“一个数字”。所以55 是第一个%d,然后第二个没有定义。

您可以尝试使用%c(一个字符)。

【讨论】:

你可能是对的。请参阅this 以供参考,但并未完全回答他的问题。 还告诉他不是死循环。相反,它正在等待再输入一个数字。 更准确地说,“d”代表“十进制”,意思是“十进制数”,也就是以10为底的数字。【参考方案2】:
printf("Enter a two digit number: ");
scanf("%1d%1d", &one, &two);

当然,即使这样也可能失败(不符合要求) 而是:

scanf("%d", &one);
if (one<10 || one>99) printf("I didn't expect that...\n");

scanf("%s",oneWord); one = atoi(oneWord);
if (one<10 || one>99)
   printf("Thats not necessarily even a number\n");
else
    two = one % 10; one = one / 10; 
       printf("The first digit is %d and the second is %d\n",one,two);
   

在后一个程序中,我们正在测试输入是否正确: 喂垃圾而不是正确的输入是一个很好的做法,看看它在哪里被忽视了。库函数 atoi(string);返回包含在字符串中的整数。如果没有找到整数,则为零。例如(atoi("a1") == 0).

但最低正确答案是

scanf("%d", number);
if (number >= 10 && number <= 99) 

   one = number / 10;  // the first digit;
   two = number % 10;  // the second digit calculated as number modulo 10


scanf("%1d%d", &one, &two);  // would halt for a single character input

【讨论】:

如果one 是单个十进制(如“d”)数字,那么它怎么可能大于9?并且本身不确定其作用的错误检查不是有效的错误检查。 尝试第一个示例并输入例如123;这不是一个两位数的数字。 我错过了您没有在第二个格式字符串中使用宽度说明符(与第一个格式字符串不同)。但是,它不能解决提问者将数字字符串分解为多个数字的问题。另外:您的第二个示例对于手头的问题来说有点过分了。也许至少解释一下你在那里做什么?【参考方案3】:

您遇到的不是无限循环,而是scanf 等待更多输入。

d-format-specifier 表示十进制数,因此可以是“0”、“41”或“2342345”。

输入第一个数字后,希望程序继续,但scanf刚刚完成第一个%d,所以scanf正在等待你完成第二个%d。这在您看来是一个无限循环,但实际上scanf 正在按照您的要求行事。

scanf 无法猜测您想要的每个数字的位数。但是你可以告诉它你想要的方式,用一个宽度说明符来说明每个信息由多少个字符组成:

#include <stdio.h>

int main () 
    int a, b;
    scanf("%2d%1d", &a, &b);
    printf("%d, %d", a, b);
 

带有错误处理:

#include <stdio.h>

int main () 
    int a, b;
    if (scanf("%2d%1d", &a, &b) < 2)
        fprintf(stderr, "not enough digits");
    else
        printf("%d, %d", a, b);

【讨论】:

还告诉他不是死循环。相反,它正在等待再输入一个数字。 天啊,没想到这么快就有这么多答案!但我最终做的是scanf("%1d%1d", &amp;one, &amp;two),与您的scanf("%2d%1d", &amp;one, &amp;two) 解决方案相比,这样做有什么问题吗? @This0nePr0grammer:你必须明白d前面的数字是什么意思:它是要解析的位数,所以对于“%3d”和数字“123456”,scanf会给你“123”。现在您应该可以自己回答问题了。 @phresnel 啊,有道理。非常感谢! :) @This0nePr0grammer 欢迎 :) (编辑:为“无限循环”添加了更详细的解释)

以上是关于为啥这个 Scanf 会导致无限循环?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 scanf() 在此代码中导致无限循环?

为啥这会导致无限请求循环?

为啥这会导致无限请求循环?

为啥意外的无限循环会增加 CPU 使用率?

为啥这个回调会产生无限循环

有人能告诉我为啥这个方法会进入无限循环吗?