为什么std :: cin的提取器操作符等待用户输入?

时间:2014-05-27 15:05:47

标签: c++ input buffer cin

我知道这可能是一个愚蠢的问题,但我不确定如何从终端获得用户输入实际上是有效的。

我从概念上理解输入/输出,我使用它们没有问题,但是当涉及到如何在基本级别实际实现这些时,我很遗憾。

据我所知,所有流对象都使用一种缓冲区。如果你提取所有到达eof的字符。这部分我可能错了,我想了解更多。例如,当我们使用std :: cin的提取器运算符时,它会等待输入。它如何区分等待输入和达到eof(没有别的东西可读)?

2 个答案:

答案 0 :(得分:8)

std::cin没有做任何特别的事情。像所有文件输入一样 在Unix中发出系统级读取(read,在{1}}中 Windows),足够的字节来填充其缓冲区(通常是一些东西 今天超过1K)。它是检测到的系统 输入来自键盘,行为不同:从文件, 系统将读取尽可能多的字节数,直到 文件结束或请求的号码,并立即返回。 通过键盘,系统通常会读取字符 进入内部缓冲区直到进入,允许编辑(返回 空间等),只有在输入时才会将此缓冲区传回 调用者(在添加新行标记之后)。

编辑:

作为摘要中的元素的摘要 讨论:我将以Unix中的情况为例 系统(但Windows基本相同,模仿它的方式 报告不同的信息)。 ReadFile本身就是 缓冲的。当您尝试提取角色时(istream 运算符,>>等),流将从中返回 它的缓冲区。如果缓冲区中没有剩余字符, 它将使用地址向系统发出istream::get请求 和它的缓冲区的大小。 (在今天的系统上,我会 惊讶地看到一个小于1K的缓冲区。)系统是什么 它取决于文件描述符指定的内容:

一个文件
系统将从当前位置复制字节 文件,直到它填满缓冲区或到达文件末尾。它 返回它复制的字节数(如果有,则返回-1 误差)。
键盘
对于键盘,系统维护一个内部缓冲区 它自己的,并逐行读取。这个缓冲区只会是 当用户按下回车时被认为是“准备好”;在那之前, 系统根本不会从`read`返回。这允许 系统实现线路编辑;例如处理像 退格。当您按Enter键时,系统会添加(系统 具体的)新的行序列到缓冲区,并返回 它已复制到缓冲区中的字符数。 (因此,不是 0,因为有新行。)可以修改此过程 有两种方式:Unix和Windows都有特殊字符 (Unix下的control-D,Windows下的control-Z)告诉了 系统从读取中立即返回,无论如何 缓冲区包含此刻。如果你刚开始 一行,缓冲区什么都不包含,`read`返回 读取0个字符,流将其视为文件末尾。 如果流缓冲区大小小于中的字符数 这条线(因为你平静地输入了100000个字符 没有新行),`read`将返回最大值 适合缓冲区,下一个`read`将立即返回 与行的其余部分(或下一个'读'将返回 立即,直到读完整行。
管道
系统将等到有任何数量 管道中请求的字符,或者没有更多 打开管道留下的进程写入。然后它会复制 要求的字符数(或更少,写入方面) 已关闭),并返回复制的数字。

如果read表示错误,则流将设置read; 如果badbit返回0个字符读取,则流将处理 它作为文件的结尾。

答案 1 :(得分:0)

std :: istream可能包含有限数量的数据(硬盘驱动器上的文件,...)或无限量的数据(传感器,...,交互式用户输入)。此外,可能还有一个代表EOF的特殊字符。

来自控制台/终端的交互式输入是无限输入。除非输入特殊字符(Linux:ctl-d),否则流永远不会达到EOF。

来自管道的非交互式输入将(应该/可能)以EOF结尾。