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

问题描述 投票:0回答:3
#include <stdio.h>
int main()
{
  int c;
  while((c=getchar())!=EOF)
  putchar(c);
  return 0;
}

在我对C的有限暴露中,只要C!= EOF,while条件将被执行,其中将基本上打印c然后等待下一个char并尝试检查是否违反条件。因此,对于我们输入的每个char,putchar将执行。然而,当我运行可执行文件时,似乎发生的事情是print语句仅在我按下新行(Enter)时才有效,并且它有某种类型的缓冲区可以在输入中打印整行。我没有看到代码中的任何缓冲区将保持字符,直到按下新行,那么这里做了什么?这些字符存储在哪里直到按下新行?

c putchar
3个回答
2
投票

当像这样从控制台读取时,你的程序实际上根本没有接收任何输入,直到你按下回车键,然后它立即读取并处理整行。

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


1
投票

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

stdinstdout,独立可以是字符,线或完全缓冲。

在您的常见情况下,两者都是行缓冲的。

在输入(getchar())被击中之前,不会给'\n'输入。 (你可以回空间输入吗?)并且在打印'\n'之前不会显示输出。


1
投票

getchar()putchar()函数是stdio包的一部分,它使缓冲输入/输出。

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

这里发生的是,在第一个getchar()上,请求一个完整的缓冲区填充,并且只用您键入的输入行部分填充。之后,所有getchar()调用从缓冲区中获取单个字符,直到它再次为空,并且那时,请求另一个完整的缓冲区。

这使得单个字符处理成为一种有效的处理方式。这也发生在输出上。 putchar()函数只填充缓冲区,直到它完全填满(或者,如果您的输出通道是tty设备,直到您请求输出\n字符),当它是,则将完整缓冲区输出到文件/设备。

此外,各种版本的unix中的终端驱动程序,在线模式下工作,这意味着直到你按下<ENTER>键,你才得到任何发送到程序的东西。这将允许您通过使用擦除键(退格键)和/或终止(Cntrl-U)键来纠正键控时所犯的错误。这是在Windows控制台应用程序中模拟的,因此您可能需要输出设备进入原始模式才能以基于字符的方式输入。

如果你想让你的程序一次读取一个字符,你需要绕过stdio的缓冲区(通过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()tcgetattr()调用,请参阅termios(4)手册页以获取有关如何执行此操作的详细信息)。在这种情况下,您必须在终止程序之前将终端状态返回到行模式,否则您将遇到麻烦。

© www.soinside.com 2019 - 2024. All rights reserved.