繁体   English   中英

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

[英]Why does std::cin's extractor operator wait for user input?

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

我从概念上理解输入/输出,我使用它们没有问题,但是当涉及到如何在基本级别实际实现它们时,我迷失了方向。

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

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

编辑:

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

一份文件
系统将从文件中的当前位置复制字节,直到它填满缓冲区或到达文件末尾。 它返回它复制的字节数(如果有错误,则返回-1)。
键盘
对于键盘,系统维护自己的内部缓冲区,并逐行读取。 当用户按下回车键时,此缓冲区仅被视为“就绪”; 在此之前,系统将不会从`read`返回。 这允许系统实现行编辑; 例如处理退格之类的东西。 当您按Enter键时,系统会将(系统特定的)新行序列添加到缓冲区,并返回其已复制到缓冲区中的字符数。 (因此,不是0,因为有新行。)此过程可以通过两种方式进行修改:Unix和Windows都有一个特殊字符(Unix下的control-D,Windows下的control-Z),它告诉系统返回立即从读取,当前缓冲区包含的内容。 如果你在一行的开头,缓冲区什么都没有,`read`返回0个字符读取,并且流将它视为文件的结尾。 如果流缓冲区大小小于行中的字符数(因为你在没有新行的情况下平静地键入了100000个字符),`read`将返回适合缓冲区的最大值,并且下一个` read`将立即返回该行的其余部分(或者下一个n`read`将立即返回,直到读取整行)。
管道
系统将等待,直到管道中请求的字符数量尽可能多,或者管道打开以进行写入时不再有剩余的进程。 然后它将复制请求的字符数(或更少,写入侧关闭),并返回复制的数字。

如果read指示错误,则流将设置badbit ; 如果read返回0个字符读取,则流将其视为文件末尾。

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM