我正在学习 C++ 并试图理解,
如果将 EOF 字符(Windows 上的 Ctrl + Z)放在行尾,为什么不打破 while 循环?
我的代码:
int main() {
char ch;
while(cin >> ch) {
cout << ch;
}
}
当我输入 ^Z 时,循环中断;
但是当我输入 12^Z 时,它没有。
我正在学习 C++ 并试图理解,
如果将 EOF 字符(Windows 上的 Ctrl + Z)放在行尾,为什么不打破 while 循环?
我的代码:
int main() {
char ch;
while(cin >> ch) {
cout << ch;
}
}
当我输入 ^Z 时,循环中断;
但是当我输入 12^Z 时,它没有。
您不会在 C++ 标准中找到问题的答案。
cin >> ch
只要既没有文件结束条件也没有输入错误,它将是“真”条件。文件结束条件的触发方式不是由语言指定的,它可以并且会因操作系统而异,甚至在同一操作系统中具有配置选项。(例如,类 Unix 系统默认使用 control-D,但可以通过stty
命令更改。)
Windows 使用 Control-Z 触发文本输入流的文件结束条件;除了在一行的开头之外,它只是碰巧没有这样做。
Unix 的行为有点不同。它在一行的开头使用 Control-D(默认情况下),或者在一行的中间使用两个Control-D。
对于 Unix,这仅适用于从终端读取;如果您从文件中读取,control-D 只是另一个非打印字符,它不会触发文件结束条件。即使从磁盘文件读取,Windows 似乎也将 control-Z 识别为文件结束触发器。
底线:不同的操作系统表现不同,主要是出于模糊的历史原因。C++ 旨在处理任何这些行为,这就是为什么它没有具体说明某些细节的原因。
C 和 C++ 标准允许文本流在默认的文本模式下做一些非常邪恶的事情。这些 Unholy Things 包括内部换行标记和外部换行控制字符之间的转换,以及将某些字符或字符序列视为表示文件结尾。在 Unix 领域它没有完成,但在 Windows 领域它已经完成,因此代码只能与原始 Unix 领域的约定相关。
这意味着在 Windows 中,没有办法编写可移植的 C 或 C++ 程序来将其输入准确地复制到其输入。
在 Unix 领域,这根本没有问题。
在 Windows 中,由单个 [Ctrl Z] 组成的行按照惯例是文件结束标记。不仅在控制台中如此,在文本文件中也是如此(取决于工具)。Windows 继承了 DOS 的这一点,后者又继承了 CP/M 的总体思想。
我不确定 CP/M 是从哪里得到的,但它只是类似于Unix 的 [Ctrl D]。
在 Unix 领域,文件结尾的一般约定只是“不再有数据”。默认情况下,在控制台中,[Ctrl D] 会将您输入的文本立即发送到等待程序。当您还没有在该行上键入任何内容时,将发送 0 个字节,并且按照惯例,返回 0 个字节的读取会遇到文件结尾。
主要区别在于,在 Windows 内部,文件标记的文本结尾是data,可以出现在文件中,而在 Unix 内部,它缺少 data,不能出现在文件中。当然,Windows 也支持文本的普通文件结尾(没有更多数据!)。这使事情变得复杂——Windows 只是更复杂。
#include <iostream>
using namespace std;
int main()
{
char ch;
while(cin >> ch) {
cout << 0+ch << " '" << ch << "'" << endl;
}
}
这是由 cin >> ^Z 将评估为 false 引起的。
更详细: cin.eof() 将返回 true ,因此隐式调用 eof() 的 while 将返回 false 并因此结束循环。
如果输入 12^Z,eof() 将返回 false,因为它可以解析有效的输入值,因此不会停止循环。
您可能也对这个 SO 感兴趣: