【问题标题】:Why is this statement printed twice in while loop?为什么这个语句在 while 循环中打印了两次?
【发布时间】:2015-06-12 16:38:06
【问题描述】:

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

#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$

【问题讨论】:

  • 因为你按了e,然后按了回车。那是两个字符。
  • k = toupper(getchar()); --> k = toupper(getchar());getchar(); 一个换行符。

标签: c loops while-loop io getchar


【解决方案1】:

发生这种情况是因为您输入了一个字母,然后按了 Enter。使用另一个 getchar() 吃掉尾随的换行符。

所以改变这个:

k = toupper(getchar());

到这里:

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

当用户输入内容时,它会进入 stdin(标准输入)流,系统会确保将用户输入的内容存储在内部缓冲区中。以下是您的代码发生的情况:

所以解决方案是吃掉尾随的换行符


复活节彩蛋提示:

你应该收到这个:

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() 上遇到了与您类似的问题,我站在您的立场上,所以当时我写下了solution

【讨论】:

  • 这有帮助。谢谢。所以每次我期望用户“输入”时,我都需要使用 getchar() 吃掉它。
  • 没错!很好的收获和很好的问题,你得到了我的 +1。 @gixxer
  • 我想还有另一种解决方案,而不是使用 getchar() 2 次,我可以使用 gets() 并从输入中删除 '\n'。
  • 正确@gixxer,看我的编辑!请改用fgets()
  • @gixxer 你现在可能已经知道了,但我添加了一张我相信会帮助未来读者的图片,希望你喜欢! :D