代码之家  ›  专栏  ›  技术社区  ›  Maxxx

在C中请求用户输入

c
  •  0
  • Maxxx  · 技术社区  · 6 年前

    我是C编程新手,我发现提示用户输入对像我这样的初学者来说是一个相当大的挑战。

    我只是在写一个简单的C代码,不断提示用户输入,直到用户输入一个负数,停止程序。在某种程度上,我希望提示用户输入的格式类似于我们在python中使用的方式,其中:

    Enter a number: (userinput a number here and press enter)
    

    输出为:

    The number you entered is 10 (for example)
    

    它不会停止循环并提示输入另一个数字,因为没有输入负数。

    Enter a number: (userinput another number which is negative)
    

    输出:

    The number you entered is -10 (for example)
    

    程序停止了。

    #include <stdio.h>
    
    int value = 0;
    while (value >= 0) {
        do {
           printf("Enter a number: ");
           scanf("%d",&value);
           printf("The number you entered is %d", &value);
    
        }
    

    但是当我运行程序时,我似乎无法首先显示“enteranumber:”语句,因为它在开始时立即请求用户输入,而没有显示提示消息,直到我输入一个整数时,提示消息才显示出来,这与我想要的相反。如果你能帮上忙我会很感激的。

    1 回复  |  直到 6 年前
        1
  •  9
  •   David C. Rankin    6 年前

    新C程序员面临的最大问题之一是正确处理用户输入,尤其是在使用 scanf 必须说明输入缓冲区中剩余的所有字符( stdin 这里)如果 匹配失败 . 为什么?当 匹配失败 发生, 扫描 在故障点停止处理字符,而导致故障的字符仍保留在输入缓冲区中 未读

    使问题更加复杂的是,两者之间的区别是什么 扫描 处理空白。数字输入说明符和 %s %s码 '\n' 在尝试下一个字符或

    也就是说,每当你使用 扫描 检查回路 因此,您可以确定用户是否使用手动生成的 EOF 是否 匹配 输入 发生故障。

    int ,您必须检查退货是否正确 1 使用前 value . 否则您可以轻松调用 未定义的行为 . 现在,仅仅检查是否发生了所有转换不允许您区分 EOF公司

    #include <stdio.h>
    
    int main (void) {
    
        int value = 0;
    
        while (value >= 0) {
            printf("Enter a number: ");
            if (scanf("%d",&value) != 1) {
                fputs ("error: invalid input\n", stderr);
                return 1;
            }
            printf("The number you entered is %d\n", value);
        }
    
        return 0;
    }
    

    使用/输出示例

    $ ./bin/scanfpos2
    Enter a number: 1
    The number you entered is 1
    Enter a number: 10
    The number you entered is 10
    Enter a number: foo
    error: invalid input
    

    ( 注: 匹配 发生故障,如果故障是一个错误,您可以通过清空输入缓冲区来采取适当的操作继续 匹配

    处理输入的正确方法 扫描 是覆盖所有潜在的错误条件,并优雅地响应 匹配 标准 扫描

    /** remove all characters that remain in stdin */
    void empty_stdin (void)
    {
        int c = getchar();
    
        while (c != '\n' && c != EOF)
            c = getchar();
    }
    

    它只读取 标准 '\n' EOF公司 遇到。再加上一个关于 扫描 将允许您处理 匹配 优雅地失败。

    #include <stdio.h>
    
    /** remove all characters that remain in stdin */
    void empty_stdin (void)
    {
        int c = getchar();
    
        while (c != '\n' && c != EOF)
            c = getchar();
    }
    
    int main (void) {
    
        int value = 0;
    
        while (value >= 0) {
            int rtn;    /* variable to store return on scanf */
    
            printf ("Enter a number: ");
            rtn = scanf ("%d",&value);
            if (rtn == EOF) {   /* handle EOF */
                fputs ("user canceled input.\n", stderr);
                break;
            }
            else if (rtn == 0) {    /* handle matching/input failure */
                fputs ("error: invalid input\n", stderr);
                empty_stdin();
            }
            else    /* good input - output value */
                printf("The number you entered is %d\n", value);
        }
    
        return 0;
    }
    

    $ ./bin/scanfpos2
    Enter a number: 1
    The number you entered is 1
    Enter a number: 10
    The number you entered is 10
    Enter a number: foo
    error: invalid input
    Enter a number: -1
    The number you entered is -1
    

    这里如果一个非整数 foo 标准

    仔细看看。C不是python。Python对您隐藏了许多实现细节,以从本质上保护您不受实例的影响,但它也有其缺点。有了C,你什么都不知道。您可以自由地写入不属于自己的内存,在转换失败后重复尝试从输入缓冲区读取数据,等等。。你对细节负责。

    最后,所有这一切都是我们接受意见的主要原因 fgets getline 建议新用户使用。有足够大的缓冲区(不要吝啬大小), fgets公司 将一次从输入缓冲区中读取一行,防止有问题的字符继续等待再次咬你。 getline公司 扫描 . 你可以随时打电话 sscanf