为什么此代码打印行而不是单个字符

时间:2019-03-16 23:55:55

标签: c putchar

#include <stdio.h>
int main()
{
  int c;
  while((c=getchar())!=EOF)
  putchar(c);
  return 0;
}

在我有限地接触C的情况下,只要C!= EOF,就会执行while条件,该条件本质上将打印c,然后等待下一个字符并尝试检查是否违反条件。因此,对于我们输入的每个字符,将执行putchar。 但是,当我运行可执行文件时,似乎发生的事情是只有当我按下换行键(Enter)时,print语句才能工作,并且它具有某种类型的缓冲区,可以在输入中打印整行。 我在代码中看不到任何将保留字符的缓冲区,直到按了新行为止,那么这里正在做什么? 这些字符存储在哪里,直到按下新行?

3 个答案:

答案 0 :(得分:2)

从这样的控制台读取时,您的程序实际上根本没有收到任何输入,除非您按Enter键,然后它会立即读取并处理整行。

您的程序不知道这些字符甚至在您按Enter键之前就存在,此时它们将被发送到stdin缓冲区。从这里开始,循环将读取并打印每个字符(包括新行),直到缓冲区为空(这意味着它将等待更多输入)或到达文件末尾为止。

答案 1 :(得分:1)

在读取数据写入数据时发生缓冲。

stdinstdout可以分别缓冲字符

在通常情况下,两者都是 line 缓冲。

在打 Enter getchar())之前,不会向'\n'提供输入。 (您可以退格输入吗?)直到输出'\n'时才显示输出。

答案 2 :(得分:1)

getchar()putchar()函数是stdio程序包的一部分,该程序包用于缓冲输入/输出。

这意味着,尽管您实际请求的字符数(仅在您的情况下为一个),缓冲机制仍使字符在缓冲区中等待,直到整个缓冲区(或{{1})为一行来自tty设备)填充。

这里发生的事情是,首先stdin要求完全填充缓冲区,并且只用您键入的输入行部分填充。之后,所有getchar()调用都使用单个字符从缓冲区开始,直到再次变空为止,然后请求另一个完整的缓冲区。

使单字符处理成为一种有效的处理方式。输出也会发生这种情况。 getchar()函数只会填充缓冲区,直到缓冲区完全填满(或者,如果您的输出通道连接到tty设备,直到您请求输出putchar()字符)为止;完整的缓冲区输出到文件/设备。

此外,各种unix的终端驱动程序都可以在行模式下工作,这意味着在您按下【{{1}】】键之前,您什么也不会发送到程序。这将允许您通过使用擦除键(退格键)和/或取消键(Cntrl-U)来更正键控上的错误。这是在Windows控制台应用程序中模拟的,因此您可能需要使输出设备进入原始模式,然后才能以基于字符的方式进行输入。

如果要使程序一次读取一个字符,则需要绕过stdio的缓冲区(通过\n函数调用,或使用<ENTER>系统调用来读取一个字符) ,可以通过以下方式完成:

setbuf(NULL)

),然后将终端驱动程序置于原始模式(通过read(2)char c; int res = read(0, &c, 1); if (res < 0) { /* error */ ... } else if (res == 0) { /* EOF in input */ ... } else { /* 1, as you requested only one char */ ... /* one character was read. */ } 调用,请参阅tcsetattr()手册页以获取有关执行此操作的详细信息),然后再进行实际阅读。在这种情况下,必须在终止程序之前将终端状态返回到线路模式,否则会遇到麻烦。