【问题标题】:Running into infinite loop with scanf使用 scanf 进入无限循环
【发布时间】:2020-05-23 16:35:24
【问题描述】:

所以我有一些这样的代码(请注意这是在 C89 中):

void inputChoice(int* choicePtr)
{
    int choice;
    printf(BLUE "\nINPUT: " RESET);                     /* Print input using the ansi colour code for Blue. */
    scanf("%d", &choice);                               /* Parse the choice. */

    while ((choice < 1) && (choice > 5))                /* Loop until choice is one of the menu options. */
    {
        /* Request for a valid menu option, printing this using the ansi colour code for Red, then resetting back to the default colour. */
        printf(RED "\nMenu Selection must be between (1 and 5) inclusive. \nPlease Re-enter. \n" RESET);
        scanf("%d", &choice);                           /* Parse the choice. */
    }
    *choicePtr = choice;                                /* Set the choice pointer to the valid choice after validation. */
}

选择哪个。它适用于整数。但如果有人输入其他任何内容,例如字符。它无限循环。 我想以某种方式检查是否输入了字符。

我尝试过的一种方法是添加它以检查是否输入了字符,因为如果扫描不正确,整数将为 0。

如下所示,但这也不起作用:

scanf("%d", &choice);

while (choice == 0)
{
    printf("Invalid Choice Re-enter.");
    scanf("%d", &choice);
}

【问题讨论】:

  • 检查什么scanf returns
  • 使用fgets()读取用户输入。

标签: c validation user-input infinite-loop c89


【解决方案1】:

表达式

while ((choice < 1) && (choice > 5))  

永远不会正确,因为choice 不能同时大于5 和小于1

你需要:

while (choice < 1 || choice > 5) 

scanf 将尝试解析缓冲区中是否有任何内容但无法解析,它将继续尝试导致无限循环,因为缓冲区中的任何内容都将保留在那里,直到成功解析为止。

由于scanf 将在未解析任何参数时返回0,因此您可以使用该信息来清除缓冲区,从而消除导致无限循环的原因:

int choice = 0;
int c; 
int scanned;
//...
if ((scanned = scanf("%d", &choice)) == EOF){ //check for EOF return
    puts("Unexpected error.");       
    //error treatment is upt to you, I would avoid the loop
    *choicePtr = scanned;
    return;
}
if (scanned == 0) {
    while ((c = fgetc(stdin)) != '\n' && c != EOF){}
}

scanfs.

Live demo

【讨论】:

  • 仅测试0 返回值是不够的:如果返回值为EOF,则choice 中的值未被读取,程序应报告意外的文件结尾。
  • 使用c 作为scanf()(转换计数)和getchar()(一个字符)的返回值会增加混乱。建议单独的变量。此外,还不清楚为什么在scanf() 返回EOF 时进入while 循环?
  • @chux-ReinstateMonica 是的,这只是一个快速修复,无论如何单独处理 EOF 更好。
  • @chux-ReinstateMonica,我想我错过了你评论的最后一部分,进入 while 循环再试一次,你认为最好中止操作?
  • @anastaciu 我认为循环不应该在scanf() EOF 返回时进入。在scanf()由于输入错误返回EOF罕见条件下,未指定下一个getchar()也必须返回EOF
【解决方案2】:

考虑到cmets的意见,这里是一个修改版:

/* reading an input choice between 1 and 5 or -1 on error */
void inputChoice(int *choicePtr) {
    int choice;

    printf(BLUE "\nINPUT: " RESET);       /* Print input using the ansi colour code for Blue. */

    for (;;) {
        int res = scanf("%d", &choice);   /* Parse the choice. */
        if (res == EOF) {
            printf(RED "unexpected end of file\n" RESET);
            choice = -1;
            break;
        }
        if (res == 0) {
            int c;
            while ((c = getchar()) != EOF && c != '\n')
                continue;
            printf(RED "invalid entry\n" "Please Re-enter.\n" RESET);
            continue;
        }
        if (choice >= 1 && choice <= 5) {
            break;
        }
        /* Loop until choice is one of the menu options. */
        /* Request for a valid menu option, printing this using the ansi 
           colour code for Red, then resetting back to the default colour. */
        printf(RED "\nMenu Selection must be between (1 and 5) inclusive.\n"
               "Please Re-enter.\n" RESET);
    }
    /* Set the choice pointer to the valid choice after validation. */
    *choicePtr = choice;
}

【讨论】:

  • 太清楚了,几乎是 dv'd,但为了我的摩托车,uv :)
  • 鉴于无名英雄已经远去,我也将获得体育精神徽章 :)
  • @anastaciu:您可能已经注意到,我们有相同的座右铭:)
  • 我们有,这只能意味着我们非常聪明 :D 奇怪的是,尽管人们普遍认为这是列奥纳多·达·芬奇的名言,但它不是很清楚,see this nice article
  • @anastaciu:非常有趣!我也喜欢 Antoine de Saint-Exupéry 的这个变体:Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. 或法语:Il semble que la perfect soit atteinte non quand il n'y a plus rien à ajouter, mais quand il n'y a plus rien à 调换器。 (Terre des Hommes, 1939)。 虽然实现完美的概念似乎雄心勃勃。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-09
  • 1970-01-01
  • 1970-01-01
  • 2011-07-14
  • 2013-10-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多