getchar() 和缓冲区顺序

getchar() and buffer order

我正在阅读的一本初学者 C 语言书籍让我对 getchar() 和缓冲区顺序(尤其是与换行相关)感到困惑。它说,

Getting rid of the Enter keypress is a problem that all beginning C programmers must face. Consider the following segment of a program:

printf("What are your two initials?\n");
firstInit = getchar();
lastInit = getchar();

You would think that if the user typed GT, the G would go in the variable firstInit and the T would go in lastInit, but that's not what happens. The first getchar() doesn't finish until the user presses Enter because the G was going to the buffer. Only when the user presses Enter does the G leave the buffer and go to the program—but then the Enter is still on the buffer! Therefore, the second getchar() sends that Enter (\n) to lastInit. The T is still left for a subsequent getchar() (if there is one).

首先,我不明白作者关于为什么 \nlastInit 而不是 T 的解释。我猜是因为我将缓冲区可视化为“先进先出”。无论哪种方式,我都不明白作者提出的顺序背后的逻辑——如果用户输入 G,然后输入 T,然后输入,G 是如何被捕获的第一个 getchar(),Enter(换行符)被第二个 getchar() 捕获,T 被第三个 getchar() 捕获?莫名其妙。

其次,我自己尝试了这个(Ubuntu 14.04 运行 on VMWare under Windows 8.1,文本编辑器 Code::Blocks,编译器 gcc),我得到了确切的作者说不会发生的常识性结果!:GfirstInitTlastInit.这是我的代码:

#include <stdio.h>

main()
{
  char firstInit;
  char lastInit;

  printf("What are your two initials?\n");

  firstInit = getchar();
  lastInit = getchar();

  printf("Your first initial is '%c' and ", firstInit);
  printf("your last initial is '%c'.", lastInit);

  return 0;
}

输出为:

What are your two initials?
GT
Your first initial is 'G' and your last initial is 'T'.

我还创建了一个后续程序,它似乎可以确认换行符最后从缓冲区中出来:

main()
{
  char firstInit;
  char lastInit;
  int newline;

  printf("What are your two initials?\n");

  firstInit = getchar();
  lastInit = getchar();
  newline = getchar();

  printf("Your first initial is '%c' and ", firstInit);
  printf("your last initial is '%c'.", lastInit);
  printf("\nNewline, ASCII %d, comes next.", newline);

  return 0;
}

输出为:

What are your two initials?
GT
Your first initial is 'G' and your last initial is 'T'.
Newline, ASCII 10, comes next.

我是不是遗漏了什么,还是作者错了? (或者这是否依赖于编译器——即使作者没有这么说)?

书籍:C 编程绝对初学者指南,第 3 版,Greg Perry,©2014,Ubuntu14.04,gcc 编译器版本 4.8.4

作者描述的是用户输入"G<enter>T<enter>"的场景。

这是一个不同的例子。对于每个输入的选项 1、2 或 3,菜单循环将迭代两次。
//while ( ( getchar ( ) != '\n')) {} 中删除注释 //,缓冲区将在每次输入后被清除,菜单每次输入仅循环一次。

#include <stdio.h>

int main()
{
    char *menu[] = { "1. first", "2. second", "3. third", "4. Exit"};
    int choice = 0;
    int each = 0;

    do {
        for ( each = 0; each < 4; each++) {
            printf ( "%s\n", menu[each]);
        }
        printf ( "\tenter choice 1-4\n");
        choice = getchar ( );
        //clear the buffer
        //while ( ( getchar ( ) != '\n')) {}
        printf ( "you entered %d %c\n", choice, choice);
    } while ( choice != '4');
    return 0;
}