为什么EOF字符如果放在一行末尾不起作用?

时间:2012-07-07 21:48:27

标签: c++

我正在学习C ++并尝试理解为什么EOF字符(Windows上的Ctrl + Z)如果放在一行的末尾就不会破坏while循环。

我的代码:

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

当我输入^ Z时,循环中断。但是当我输入12 ^ Z时,它没有。为什么呢?

3 个答案:

答案 0 :(得分:8)

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

只要既没有文件结束条件也没有输入错误,

cin >> ch将是一个“真实”条件。语言未指定如何触发文件结束条件,并且它可以并且将随操作系统的不同而不同,甚至可以在同一操作系统中使用配置选项。 (例如,类Unix系统默认使用control-D,但可以通过stty命令更改。)

Windows使用Control-Z触发文本输入流的文件结束条件;除了在一行的开头,它恰好不会这样做。

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

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

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

答案 1 :(得分:2)

C和C ++标准允许文本流在文本模式中执行非常不合理的事情,这是默认设置。这些邪恶事物​​包括内部换行标记和外部换行控制字符之间的转换,以及将某些字符或字符序列视为表示文件结尾。在Unix-land中它还没有完成,但在Windows-land中已经完成,因此代码只能与原始的Unix-land约定相关。

这意味着在Windows中,无法编写可将其输入完全复制到其输入的可移植C或C ++程序。

在Unix-land中,这根本不是问题。

在Windows中,由单个[Ctrl Z]组成的行按照惯例是文件结束标记。这不仅在控制台中,而且在文本文件中(取决于工具)。 Windows从DOS继承了这一点,后者继承了CP / M的一般思想。

我不确定CP / M从哪里获得它,但它只是类似的,而不是完全相同!,就像Unix'[Ctrl D]。

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

主要区别在于Windows内部文件标记的文本末尾是 data ,这可能发生在文件中,而在Unix内部则缺少数据,哪个不能在文件中出现。当然,Windows还支持文本的普通文件结尾(没有更多数据!)。这使事情变得复杂--Windows只是更复杂。


#include <iostream>
using namespace std;

int main()
{
    char ch;
    while(cin >> ch) {
        cout << 0+ch << " '" << ch << "'" << endl;
    }
}

答案 2 :(得分:1)

这是由cin&gt;&gt;引起的^ Z将评估为false。

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

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

您可能也对此感兴趣:

SO on semantics of flags