为什么 EOF 字符放在行尾不起作用?



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

我的代码:

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

当我输入^Z时,循环中断
但当我输入12^Z时,它不会。

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

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

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

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

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

一句话:不同的操作系统表现不同,主要是由于模糊的历史原因。C++被设计用于处理这些行为中的任何一种,这就是为什么它在某些细节上并不具体。

C和C++标准允许文本流在默认的文本模式中做一些不愉快的事情。这些不愉快的事情包括内部换行标记和外部换行控制字符之间的转换,以及将某些字符或字符序列视为表示文件结束。在Unix领域,它还没有完成,但在Windows领域,它已经完成了,所以代码只能与原始的Unix领域约定相关。

这意味着在Windows中,没有办法编写一个可移植的C或C++程序来将其输入精确地复制到其输入中。

在Unix领域,这根本没有问题。

在Windows中,由单个[Ctrl Z]组成的行通常是文件结束标记。这不仅在控制台中是如此,在文本文件中也是如此(这在一定程度上取决于工具)。Windows从DOS继承了这一点,DOS又继承了CP/M的总体思想。

我不确定CP/m是从哪里来的,但它只是相似的,一点也不一样!,作为Unix的[Ctrl D]。

在Unix领域,文件结尾的一般约定只是"不再有数据"。在控制台中,[Ctrl D]默认情况下会立即将您键入的文本发送到等待的程序。当您还没有在行上键入任何内容时,将发送0个字节,并且按照惯例,返回0个字节的读取会遇到文件结尾。

主要区别在于,在Windows内部,文件的文本结尾标记为数据,这可能发生在文件中,而在Unix内部,这是缺少数据


#include <iostream>
using namespace std;
int main()
{
    char ch;
    while(cin >> ch) {
        cout << 0+ch << " '" << ch << "'" << endl;
    }
}

这是由cin>>^Z计算为false引起的。

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

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

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

关于标志语义的SO

相关内容

  • 没有找到相关文章