无法弄清楚为什么 getchar() 在 C 中第一次出现时选择换行符

Can't figure out why getchar() is picking up newline for first occurence in C

我正在参加关于 "C" 和 运行 解决问题的培训课程。很难解释,所以我将 post 代码。这是训练语法,所以不要问我为什么要这样做。当这两个段块在 main() 中都是 运行 时,第二个块的行为就好像它单独存在于 main() 中一样。我已经尝试了几次 IDE 认为这可能是一个错误。

/* First Segment Block */
int c;
printf("Type a letter: ");
c = getchar();
printf("You typed '%c'\n",c);

/* OR - outputs the same, to demonstrate putchar */

printf("You typed '");
putchar(c);
printf("'\n\n");

/* Second Segment Block */
int a,b,d;
printf("Type two letters: ");
a = getchar();
b = getchar();
d = getchar();
printf("You typed '");
putchar(a);
printf("' and '");
putchar(b);
printf("' and '");
putchar(d);
printf("'\n");

在第二段块中,我添加了第三个变量来测试我的理论。当您输入要求的 2 个字母时,第一个 getchar() 会换行,第二个 getchar() 会选择第一个字母。第三个 getchar() 获取第二个字母。如果注释掉整个第一个段块,那么它会正确运行,第一个 getchar() 获取第一个字母,第二个 getchar() 获取第二个字母,按预期显示输出。

这是 运行 一起时的输出。

Type a letter: k
You typed (k)
You typed 'k'

Type two letters: lk
You typed '
' and 'l' and 'k'

RUN SUCCESSFUL (total time: 9s)

当它们分别运行时,输出如下。

第一段输出.

Type a letter: k
You typed (k)
You typed 'k'

RUN SUCCESSFUL (total time: 5s)

第二段输出。

Type two letters: rf
You typed 'r' and 'f' and '
'

RUN SUCCESSFUL (total time: 5s)

第三个 getchar() 是一个换行符,这是预期的。

谁能解释为什么当两个段都在同一个 main() 中 运行 时,行为与 运行 分开时的行为不同?

提前谢谢你, Daniel N. (C语言初学者)

'space'和'\n(新行)'也是字符。因此,getchar() 获取您输入的每个字符。例如,如果您按 'a (enter) b',它将读取 a='a',b='\n',d='b'.

发生这种情况是因为您的终端是行缓冲的,因此在将您键入的 任何 字符传递给您的程序之前,它会等待您按 Enter 键。当您按下 Enter 键时,您的程序将接收您键入的任何字符,包括 由 Enter 键生成的换行符 (\n)。

实际的事件顺序是这样的:

  1. 您的程序打印第一个提示。
  2. 您的程序调用 getchar(),它试图从标准输入流中读取一个字符。由于流当前为空,它会暂停您的程序,直到有一些输入到达。
  3. 您看到提示并按下一个键(例如,X)。由于您的终端是行缓冲的,您的程序还没有看到它,因此保持暂停状态。
  4. 您按回车键。您的终端现在将您键入的字符(X\n)发送到您的程序。
  5. getchar() returns 您的程序在标准输入上可用的第一个字符,即 X.
  6. 您的代码现在打印第二个提示,并再次调用 getchar()getchar() 看到还有另一个字符 (\n) 仍在等待标准输入,并立即 returns 它。

这就是输入流的样子。 当第一段是 运行 并输入第一个字符时,按回车键。它基本上被当作输入流中的字符本身。因此,如果您输入 'a' 并按回车键,它就像输入流中的 'a\n' 一样。 现在使用 getchar,你从输入流中读取一个字符到你的变量,这里是 'a'。在给你 'a' 时,输入流仍然保留 '\n'。 下次你做 getchar 时,你会得到 '\n' 作为 char。即使您输入新字符,它也将始终在流中排在第一位,即 '\nabc....'

'\n'只是为了解释换行符。

在第一个提示符下,您键入类似 aEnter 的内容,因此您的输入流包含字符 'a', '\n'。第一个 getchar 调用读取 a 并在输入流中留下换行符。

为了响应第二个提示,您键入 bcEnter,因此您的输入流现在包含 '\n', 'b', 'c', '\n'

您或许可以从这里弄清楚发生了什么 - 下一个 getchar 调用从输入流中读取换行符。

有几种方法可以解决这个问题。一种是测试你的输入,如果是换行再试:

do
{
  a = getchar();
} while ( a == '\n' );  // or while( isspace( a )), if you want to reject
                        // any whitespace character.

另一种是不使用getchar;相反,使用带有 %c 转换说明符的 scanf 和格式字符串中的空白 space:

scanf( " %c", &c ); // you will need to change the types of your 
...                 // variables from int to char for this.
scanf( " %c", &a );
scanf( " %c", &b );
scanf( " %c", &c );

格式字符串中的前导 space 告诉 scanf 忽略任何前导白色 space,因此您不会选择换行符。