getchar() 实际上并没有从用户那里获取输入

getchar() doesn't actually take input from user

本文关键字:用户 那里 获取 输入 并没有 实际上 getchar      更新时间:2023-10-16

我正在用C++编写一个灵活的命令行(但不会太长!)菱形方形生成器。我刚刚写完了用户输入的一半。然而,在最后一个命令中,输入"slips",并自动向getchar()输入一行换行符。我已经采取了预防措施,以确保它不会出现任何类型的溢出,即同时刷新stdin和stdout。问题仍然存在。这是我的代码:

#include <stdio.h>
#include <stdlib.h>
int main () {
    unsigned  long seed = 0, x = 0, y = 0, initial = 0, range = 0;
    int smooth = 0, fail = 1;
    char flagchar1 = 'n';
    printf("Welcome to my diamond-square generator! This isn't full-feature yet, so I'm just gonna have you input the variables one by one. ");
    do {
        printf("Please input the seed (this is a positive integer):n");
        fail = scanf("%lu", &seed);
        while (fail == 0) {
            printf("Try again, smartass.n");
            fail = scanf("%lu", &seed);
        }
        fail = 1;
        printf("Now input the x, or horizontal, size of your grid:n");
        fail = scanf("%lu", &x);
        while (fail == 0) {
            printf("An integer. Not a string. An integer. You can do that, can't you?n");
            fail = scanf("%lu", &x);
        }
        fail = 1;
        printf("Now input the y, or vertical, size of your grid:n");
        fail = scanf("%lu", &y);
        while (fail == 0) {
            printf("What was that supposed to be? An integer, please.n");
            fail = scanf("%lu", &y);
        }
        fail = 1;
        printf("Now input about how high you'd like the grid to be (this goes from a scale of 1 to 256):n");
        fail = scanf("%lu", &initial);
        while (initial == 0 || initial > 256 || fail == 0) {
            printf("ahahahahaha how HIGH do you have to be just to HAVE that hieght........n");
            fail = scanf("%lu", &initial);
        }
        fail = 1;
        printf("Now input the range of the heights on your grid (this must be equal to or less than 256):n");
        scanf("%lu", &range);
        while (range >= 256 || fail == 0) {
            printf("What did I say about being equal to or less than 256? Give me something reasonable to work with here.n");
            fail = scanf("%lu", &range);
        }
        fail = 1;
        printf("Just one more variable to go! Now, I need you to input the smoothness of your grid. Smaller numbers make spikier grids. You can make this negative, but beware!n");
        fail = scanf("%d", &smooth);
        while (fail == 0) {
            printf("That... was not a number.n");
            fail = scanf("%d", &smooth);
        }
        fail = 1;
        printf("nOkay. Are these the values you want?n   Seed:       %lun   Width:      %lun   Length:     %lun   Height:     %lun   Range:      %lun   Smoothness: %dnDo you want to keep these? Type Y/n.n", seed, x, y, initial, range, smooth);
        fflush(stdin);
        fflush(stdout);
        flagchar1 = getchar();
    } while (flagchar1 != 'y' && flagchar1 != 'Y' && flagchar1 != 'n');
}

这是我的输出,程序已经结束(如果我从while()中删除&& flagchar1 != 'n',程序只重复整个do-while循环):

欢迎使用我的菱形发电机!这还不是全部功能,所以我只是让你一个接一个地输入变量。请输入种子(这是一个正整数):12345678现在输入网格的x或水平大小:40现在输入网格的y或垂直大小:30现在输入您希望网格的高度(从1到256):1288哈哈哈哈,你必须有多高才能拥有它。。。。。。。。128现在输入网格上的高度范围(必须等于或小于256):30还有一个变量!现在,我需要您输入网格的平滑度。数字越小,网格越尖。你可以说这是负面的,但要小心!10可以这些是你想要的价值观吗?种子:12345678宽度:40长度:30高度:128范围:30平滑度:10你想保留这些吗?类型Y/n。

发生了什么,我该如何解决?

附言:我知道我的输入验证基本上是无用的。我们也非常感谢您的帮助。

让循环的结尾看起来像这样:

    // Ignore remaining characters on current line.
    int ch;
    while( (ch = getchar()) != EOF && ch != 'n')
      ;
    // fetch first character on next line
    flagchar1 = getchar();
} while (flagchar1 != 'y' && flagchar1 != 'Y' && flagchar1 != 'n');

上次调用scanf后,您将把'n'留在stdin中。

您不能依赖fflush(stdin)具有任何特定行为。对输入流调用fflush的结果是未定义的。请参阅使用fflush(stdin)

代码的行为完全符合您的要求。如果用户输入"y"、"y"或enter,while循环中的其中一个条件将为false,从而导致它退出。

你想要的是:

while (flagchar1 == 'y' || flagchar1 == 'Y' || flagchar1 == 'n');

编辑:我还将删除fflush(stdin),并用fgets()替换getchar()。这将保证在不必使用fflush的情况下读取整行,这可能是问题所在。

我猜你在Linux上?这在Windows中的VS上运行良好。它提示,从键盘上读取,如果检查,则包含问题中正确的"y"或"y"。

我可能建议您尝试将最后一次扫描更改为:

fail = scanf("%d ", &smooth);

你也可以试着调用fpurge()而不是fflush(),但这不是标准的,我认为格式字符串末尾的空格会得到你想要的。

尾部空格将要求scanf在输入数据中使用任何额外的空白(包括换行符)。fflush()可能不会执行您想要的输入操作。

我怀疑无论你使用什么系统,都会将回车留在流中,如果你将flagchar1打印为int,你会得到10?

建议:

  1. 使用C++流
  2. 在比较字符之前,请使用tolowertoupper
  3. 使用std::string

使用fgets, gets, fflush, strcmp,的C语言在这方面存在许多问题。C++语言已经解决了std::stream类中的许多问题。

由于您没有使用C++功能,因此应该将C++标记更改为C

尝试

}while(flagchar1!='y'|flagcchar1!='y'|flacchar1!='\n');

而不是

}while(flagchar1!='y'&flagcchar1!='y'&flagchar1!='\n');

相关文章: