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

标签 c++ input buffer cin

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

我从概念上理解输入/输出,使用它们也没有问题,但当涉及到这些在基本层面上的实际实现方式时,我就迷失了。

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

最佳答案

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

编辑:

有点像对在 讨论:我将以 Unix 中发生的事情为例 系统(但 Windows 基本相同,取模方式 报告不同的信息)。 istream 本身是 缓冲的。当您尝试提取字符(>>> 运算符、istream::get 等),流将从 它的缓冲区。如果缓冲区中没有更多字符, 它将向系统发出一个read请求,地址为 及其缓冲区的大小。 (在今天的系统上,我会 惊讶地看到不到 1K 的缓冲区。)什么系统 用它做什么将取决于文件描述符指定的内容:

一个文件
系统将从当前位置开始复制字节 文件,直到它填满缓冲区或到达文件末尾。它 返回它复制的字节数(或 -1,如果有 错误)。
键盘
对于键盘,系统维护一个内部缓冲区 它自己的,并逐行读取。这个缓冲区只会 当用户按下 enter 时被视为“准备就绪”;在此之前, 系统根本不会从 read 返回。这允许 执行行编辑的系统;例如处理类似的事情 退格键。当您按下回车键时,系统会添加(系统 特定的)新行序列到缓冲区,并返回 它已复制到缓冲区中的字符数。 (因此,不 0,因为有换行。)这个程序可以修改 两种方式:Unix 和 Windows 都有特殊字符 (Unix 下的 control-D,Windows 下的 control-Z)告诉 系统立即从读取返回,无论 缓冲区目前包含。如果你刚开始 一行,缓冲区不包含任何内容,`read` 返回 读取了 0 个字符,流将其视为文件结尾。 如果流缓冲区大小小于中的字符数 该行(因为你已经冷静地输入了 100000 个字符 没有新行),`read` 将返回将要返回的最大值 适合缓冲区,下一个 read 将立即返回 与该行的其余部分(或下一个 `read` 将返回 立即,直到读完整行)。
一个管道
系统会等到有足够多的 管道中请求的字符,或者没有更多 留下管道以供写入的进程。然后它会复制 请求的字符数(或更少,写入端 关闭),并返回复制的数字。

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

关于c++ - 为什么 std::cin 的提取器操作符等待用户输入?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23892889/

相关文章:

c++ - 如何使用 CMake 正确链接外部库?

c++ - 用C/C++实现执行超时

python - 用超时跳过输入函数

php - 使用 PHP 如何每隔一定时间回显内容?

c++ - 用于中间插入和随机访问的性能良好的顺序容器

java - Java 和 C++ 在对象创建方面的主要区别是什么?

javascript - Opera 中的输入类型文件

css - 使用css的文本输入控件不会丢失 "Focus"样式

c - 如何清理使用 read() 填充的缓冲区并继续读取同一缓冲区?

java - BufferedReader 默认缓冲区大小?