13

我正在学习 C++ 并试图理解,
如果将 EOF 字符(Windows 上的 Ctrl + Z)放在行尾,为什么不打破 while 循环?

我的代码:

    int main() {
        char ch;
        while(cin >> ch) {
            cout << ch;
        }
    }

当我输入 ^Z 时,循环中断;
但是当我输入 12^Z 时,它没有。

4

3 回答 3

9

您不会在 C++ 标准中找到问题的答案。

cin >> ch只要既没有文件结束条件也没有输入错误,它将是“真”条件。文件结束条件的触发方式不是由语言指定的,它可以并且会因操作系统而异,甚至在同一操作系统中具有配置选项。(例如,类 Unix 系统默认使用 control-D,但可以通过stty命令更改。)

Windows 使用 Control-Z 触发文本输入流的文件结束条件;除了在一行的开头之外,它只是碰巧没有这样做。

Unix 的行为有点不同。它在一行的开头使用 Control-D(默认情况下),或者在一行的中间使用两个Control-D。

对于 Unix,这仅适用于从终端读取;如果您从文件中读取,control-D 只是另一个非打印字符,它不会触发文件结束条件。即使从磁盘文件读取,Windows 似乎也将 control-Z 识别为文件结束触发器。

底线:不同的操作系统表现不同,主要是出于模糊的历史原因。C++ 旨在处理任何这些行为,这就是为什么它没有具体说明某些细节的原因。

于 2012-07-07T22:25:00.893 回答
4

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;
    }
}
于 2012-07-07T22:25:53.453 回答
1

这是由 cin >> ^Z 将评估为 false 引起的。

更详细: cin.eof() 将返回 true ,因此隐式调用 eof() 的 while 将返回 false 并因此结束循环。

如果输入 12^Z,eof() 将返回 false,因为它可以解析有效的输入值,因此不会停止循环。

您可能也对这个 SO 感兴趣:

SO关于标志的语义

于 2012-07-07T21:59:35.303 回答