为什么这个语句在 while 循环中会被打印两次?

5
我写了这个简单的程序来练习:

我为练习编程写了这个简单的程序:

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

#define CLASSES 3
#define STUDENTS 4
int grades[CLASSES][STUDENTS];

int main(void)
{
    int i = 1;
    char t,k;
    while(i == 1)
    {
        printf("\n\n\nMENU:\nEnter the grades(E)\nReport Grades(R)\nQuit(Q)\nYour choice: ");
        k = toupper(getchar());
        printf("Input entered... %c\n", k);
        switch(k) {
            case 'E' : 
                printf("Entering the grades..\n");
                break;
            case 'R' :
                printf("Reporting the grades...\n");
                break;
            case 'Q' :
                printf("Quitting the program...\n");
                exit(0);
                break;
            default:
                printf("ERROR: %c: Incorrect menu option\n", k);
                break;
        }

    }
    return 0;
}

当我运行这个程序时,它首先要求我输入一个选项。如果我输入'E'或'R',它会进入相应的'case'块,但在while循环的下一次迭代中,它不等待我输入我的选择。相反,它假定我输入了“NULL”,并第三次要求我的提示。每次我输入一个选项时,这种情况都会发生。以下是此程序的输出。我错过了什么?
host-mb:c_practice host$ ./asd



MENU:
Enter the grades(E)
Report Grades(R)
Quit(Q)
Your choice: E
Input entered... E
Entering the grades..



MENU:
Enter the grades(E)
Report Grades(R)
Quit(Q)
Your choice: Input entered...

ERROR:
: Incorrect menu option



MENU:
Enter the grades(E)
Report Grades(R)
Quit(Q)
Your choice: R
Input entered... R
Reporting the grades...



MENU:
Enter the grades(E)
Report Grades(R)
Quit(Q)
Your choice: Input entered...

ERROR:
: Incorrect menu option



MENU:
Enter the grades(E)
Report Grades(R)
Quit(Q)
Your choice: Q
Input entered... Q
Quitting the program...
host-mb:c_practice host$

2
因为你按了e键,然后按了回车键。这是两个字符。 - user253751
k = toupper(getchar()); --> k = toupper(getchar());getchar(); 一个是为了读取新行。 - BLUEPIXY
1个回答

13

这是因为您输入一个字符然后按回车键。使用另一个getchar()函数来处理末尾的换行符。

所以将代码更改为:

k = toupper(getchar());

到这个:

k = toupper(getchar());
getchar(); // eat the trailing newline

当用户输入数据时,它会被发送到标准输入流stdin中,并且系统会确保将用户输入的内容存储在内部缓冲区中。以下是关于你的代码发生的情况:

enter image description here

所以解决方法是消耗掉换行符


彩蛋提示:

您应该收到这个:

warning: implicit declaration of function ‘printf’

因为你缺少IO头文件,所以你应该在主文件的顶部添加以下内容:

#include <stdio.h>

同样,您应该添加:

#include <ctype.h>  // for toupper()
#include <stdlib.h> // for exit()

另一个解决方案是使用fgets(),请参阅此问题以获取更多信息:C- scanf() vs gets() vs fgets()


我和你遇到了类似的问题,使用scanf()时也曾陷入困境,所以我当时记录下了解决方案


很有帮助。谢谢。所以每次当我期望用户输入“Enter”时,我需要用getchar()函数来读取它。 - gixxer
没错!很好的发现和问题,你得到了我的加一。@gixxer - gsamaras
我猜还有另一种解决方案,而不是使用两次getchar(),我可以使用gets()并从输入中去掉'\n'。 - gixxer
正确的@gixxer,看我的编辑!使用fgets()代替! - gsamaras
@gixxer,你可能已经明白了,但我添加了一张图片,我相信这将有助于未来的读者,希望你喜欢!:D - gsamaras
@gixxer 实际上,连续调用两次getchar()可能非常不明智。如果用户输入0或2个以上字符,然后按下回车键,程序将开始表现异常。因此,最好使用这个k = toupper(getchar()); if (k != '\n') while (getchar() != '\n') {} 或者 [f]gets() 调用。 - HolyBlackCat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接