【问题标题】:infinite loop in C when the user enters a character instead of a number当用户输入字符而不是数字时,C 中的无限循环
【发布时间】:2020-11-13 19:09:16
【问题描述】:

我有一个问题,我想让用户输入一个从 1.00 到 10.00 的数字,如果他输入的数字超出该范围,我会显示他错了,然后重试。我认为我做得很好,但问题是如果用户输入一个字母循环无限重复,我会很感激你的帮助。谢谢你。 :)

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

int main()
{
    float a;

    do
    {
        printf("Insert number between 1.00 and 10.00:\n");
        scanf("%f", &a);

        if (a < 1.00 || a > 10.0)
        {
            printf("Insert a correct number.\n");
        }
    } while (a < 1.00 || a > 10.00);

    system("pause");
    return 0;
}

【问题讨论】:

  • scanf 返回一个值。您需要检查它是否能够读取任何内容。

标签: c loops if-statement scanf do-while


【解决方案1】:

scanf 将 '\n' 字符留在输入流中,因此您需要跳过它:

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

int main()
{
    float a;

    do
    {
        printf("Insert number between 1.00 and 10.00:\n");
        scanf(" %f", &a);

        if (a < 1.00 || a > 10.0)
        {
            printf("Insert a correct number.\n");
        }
    } while (a < 1.00 || a > 10.00);

    printf("\nyou have entered: %f\n", a);

    return 0;
}

https://godbolt.org/z/baPxdn。但是并没有解决输入错误的问题。

我个人更喜欢阅读该行然后扫描它(它确实解决了所有问题):

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

int main()
{
    char str[100];
    float a;

    do
    {
        printf("Insert number between 1.00 and 10.00:\n");
        fgets(str, 100, stdin);
        if(sscanf(str, " %f", &a) != 1) continue;

        if (a < 1.00 || a > 10.0)
        {
            printf("Insert a correct number.\n");
        }
    } while (a < 1.00 || a > 10.00);

    printf("\nyou have entered: %f\n", a);

    return 0;
}

https://godbolt.org/z/vxY7To

【讨论】:

  • 第二种方案有什么优势吗?
  • @Majkl 第一个只消耗空格
  • %f 已经消耗了前导空格,因此您的第一个程序与 OP 程序具有相同的行为(显然最终输出语句除外)
  • @M.M 关于“第一个程序具有相同的行为”是正确的,但这会导致“但它没有解决错误的输入问题”和第二个代码。确实空间是" %f" 是多余的。
  • @chux-ReinstateMonica 为什么要发布相同的程序作为导入?我认为它具有误导性,因为它的前缀是注释 ​​"scanf leave the '\n' char in the input stream so you need to skip it:" ,所以 OP 可能会读到它并认为添加空格有一些效果。它没有。事实上, '\n' chars 从来没有任何问题。唯一的问题是没有正确处理字母。
【解决方案2】:

当您尝试在无效输入上运行scanf() 时,它不会更新a,因为这是不可能的,因此您的循环将永远继续,因为a 永远不会更新并且scanf 函数将永远失败,什么都没有实际上是由scanf“读取”的,并且永远不会通过无效输入。

确保在重复循环之前通过“消耗”它们来处理无效输入。

【讨论】:

    【解决方案3】:

    您必须检查“scanf”的结果,并在发生错误时“清理”IO 流缓冲区。

    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>
    #define CLEAN_STD_STREAM() \
     do{\
       int ch; \
       while ((ch = getchar()) != '\n' && ch != EOF); \
     }while(0)
    
    int main()
    {
        float a;
    
        do
        {
            printf("Insert number between 1.00 and 10.00:\n");
            if(scanf("%f", &a) != 1)
            {
              CLEAN_STD_STREAM();//fflush() dosen't work on the Linux
              continue;
            }
    
            if (a < 1.00 || a > 10.0)
            {
                printf("Insert a correct number.\n");
            }
        } while (a < 1.00 || a > 10.00);
    
        system("pause");
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-04-03
      • 1970-01-01
      • 2014-06-18
      • 2022-01-10
      • 1970-01-01
      • 2015-07-19
      • 2020-08-07
      相关资源
      最近更新 更多