循环跳过 C 中的 getchar?

Loop skips over getchar in C?

提问人:Ian 提问时间:10/30/2023 最后编辑:Vlad from MoscowIan 更新时间:10/30/2023 访问量:115

问:

我正在用 C 语言编写一个简单的程序,该程序要求用户在循环中输入,直到他们在出现提示时输入字母。但是,当我运行程序时,它会立即跳过输入字符的提示,并要求用户输入另一个输入。知道为什么会发生这种情况以及我该如何解决它吗?Q

这是我的代码:

    while (exit != 'q' && exit != 'Q') {
        printf("Please enter the grade for assignment #%d: ", assignmentNumber);
        scanf("%lf", &gradeInput);

        printf("Press q to quit, press any other character to continue: ");
        exit = getchar();
    } 

我尝试将其更改为,就像我看到有人在有类似问题的帖子下建议一样。它确实使输入字符的提示实际上起作用,但是输入时循环不再结束。getcharscanf(%c%*c)Q

c while-循环 getchar

评论

4赞 pmg 10/30/2023
不要混用 和 .最好专门用于所有用户输入(用于等级,用于退出字符,... 不是为用户输入而设计的; 单独可以成为 PITA; 就像类固醇一样工作。scanf()getchar()fgets()scanf()getchar()fgets()getchar()
0赞 Weather Vane 10/30/2023
scanf() 的副本将换行符字符保留在缓冲区中

答:

0赞 Jibel 10/30/2023 #1

看起来您面临的问题与读取双精度符 (with ) 后留在输入缓冲区中的换行符影响 的行为的方式有关。该函数从输入缓冲区中读取下一个字符,其中包括任何剩余的换行符。scanf("%lf", &gradeInput)getchar()getchar()

若要解决此问题,可以在读取成绩后通过使用换行符来清除输入缓冲区。下面是代码的更新版本:

#include <stdio.h>

int main() {
    char exit = ' ';
    double gradeInput;
    int assignmentNumber = 1;

    do {
        printf("Please enter the grade for assignment #%d: ", assignmentNumber);

        if (scanf("%lf", &gradeInput) != 1) {
            printf("Invalid input. Please enter a valid number.\n");
            while (getchar() != '\n'); // Clear the input buffer
            continue;
        }

        while ((exit = getchar()) != '\n' && exit != EOF); // Clear the input buffer

        printf("Press q to quit, press any other character to continue: ");
        exit = getchar();
        while (getchar() != '\n'); // Clear the input buffer

        assignmentNumber++;
    } while (exit != 'q' && exit != 'Q');

    return 0;
}

在此代码中,我们使用 while 循环通过读取字符来清除输入缓冲区,直到遇到换行符。这可确保在尝试读取退出字符之前,从输入缓冲区中删除任何剩余字符(包括换行符)。这应该可以解决问题,并允许您的循环在进入或进入时结束。Qq

评论

0赞 Jibel 10/30/2023
@chqrlie我修好了
2赞 Ted Lyngmo 10/30/2023
吉贝尔,我想你误解了@chqrlie说的话。你仍然有潜在的无限循环。while (getchar() != '\n');
1赞 ad absurdum 10/30/2023
其他评论者说的是,您也需要检查,因为出于多种原因可能会返回此内容。像这样的东西:是传统的。EOFgetchar()int c; while ((c = getchar()) != '\n' && c != EOF) { continue; }
0赞 Jibel 10/30/2023
@adabsurdum 它是否在新编辑中修复?
1赞 chqrlie 10/30/2023
你还有两个潜在的无限循环。也应该有 type ,而不是 。您应该在 / 循环的子句中测试。使用带有显式测试和语句的循环将更具可读性,并允许更好的一致性。while (getchar() != '\n')exitintcharEOFwhiledowhilefor(;;)break
2赞 Vlad from Moscow 10/30/2023 #2

这个电话getchar

exit = getchar ();

可以读取换行符。'\n'

相反,请更改语句,例如

scanf( " %c", &exit );
        ^^^

前提是 .exitchar

注意格式字符串中的前导空格。它允许跳过空格字符。

此外,最好将 while 循环更改为 do-while 循环,例如

do 
{
    printf("Please enter the grade for assignment #%d: ", assignmentNumber);
    scanf("%lf", &gradeInput);

    printf("Press q to quit, press any other character to continue: ");
    scanf( " %c", &exit );
} while ( exit != 'q' && exit != 'Q' );
3赞 chqrlie 10/30/2023 #3

问题是从输入行中读取用户键入的浮点数后的下一个字符。这可以是任何内容,但在大多数情况下,当用户按下键时,此字符将是存储在输入流中的换行符。getchar()Enter

您应该将程序修改为:

  • 一次读取一行输入
  • 检查文件末尾
  • 检查用户输入是否成功转换为数字

这是一个修改后的版本:

#include <stdio.h>

int main() {
    double gradeInput;
    int assignmentNumber = 1;

    for (;;) {
        char input[128];
        printf("Please enter the grade for assignment #%d: ", assignmentNumber);
        if (!fgets(input, sizeof input, stdin)) {
            /* end of file */
            break;
        }
        if (sscanf(input, "%lf", &gradeInput) != 1) {
            printf("invalid input: %s\n", input);
            continue;
        }
        /* handle the grade */
        // [...]
        assignmentNumber++;

        printf("Press q to quit, press any other character to continue: ");
        if (!fgets(input, sizeof input, stdin)) {
            /* end of file */
            break;
        }
        if (input[0] == 'q' || input[0] == 'Q')
            break;
    }
    return 0;
}