cin.eof()和feof(stdin)不一致 [英] cin.eof() and feof(stdin) are discordant

查看:122
本文介绍了cin.eof()和feof(stdin)不一致的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可以 feof(stdin) cin.eof( ) 会产生不一致的结果吗?我希望他们不要这样做,但是我想我缺少了一些东西。标准是否对此有任何说明?

Can feof(stdin) and cin.eof() produce discordant results? I would expect them not to do so, but I guess I am missing something. Does the standard say anything about this?

在未提供任何输入的情况下,请考虑以下示例。可以通过在终端中键入EOF的快捷方式,或通过重定向 / dev / null (Unix)上的输入,或在 ideone.com ...

Consider the following example, when no input is given. This can either be done by typing the shortcut for EOF in the terminal, or by redirecting the input on /dev/null (Unix), or with empty stdin sequence on ideone.com...

#include <cstdio>
#include <iostream>

int main() {
    using namespace std;

    char ch;
    cin >> ch;

    cin.clear();

    cout << boolalpha
         << "feof(stdin): " << bool(feof(stdin)) << endl
         << "cin.eof(): " << cin.eof() << endl;
}

输出:

feof(stdin): true
cin.eof(): false


推荐答案

好吧,这并不奇怪。

std :: cin 是在C ++库中真正定义的,但是 stdin 是在C标准库中定义的,该标准库是C ++的成员之一,主要是出于兼容性方面的考虑。

std::cin is truely defined in the C++ library, but stdin is defined in the C standard library that is member of the C++ one mainly for compatibility reasons.

C ++ 17的草稿n4659说:

Draft n4659 for C++17 says:


30.4.3窄流对象[narrow.stream.objects]

30.4.3 Narrow stream objects [narrow.stream.objects]

istream cin;

1对象cin控制与对象 stdin相关联的流缓冲区的输入,以
(30.11.1)声明。

1 The object cin controls input from a stream buffer associated with the object stdin, declared in (30.11.1).

及更高版本:


30.11 C库文件[c.files]

30.11.1标头< cstdio> 提要[cstdio.syn]

...

1标头的内容和含义< cstdio> 与C标准库头文件< stdio.h> 相同。

30.11 C library files [c.files]
30.11.1 Header <cstdio> synopsis [cstdio.syn]
...
1 The contents and meaning of the header <cstdio> are the same as the C standard library header <stdio.h>.

这意味着 cin 是C ++流 wrapping 底层的 stdin C FILE对象。结果,当您尝试在到达文件末尾后从 cin 中读取字符时, cin 将从 stdin 询问, stdin 将报告文件结束情况,并且两个 cin stdin 将设置其内部文件结尾标志。然后,对 cin.clear()的调用将清除C ++流标志,但未指定它是否对 stdin 对象内部标志。

That means that cin is a C++ stream wrapping the underlying stdin C FILE object. As a result, when you try to read a character from cin after reaching the end of file, cin will ask it from stdin, stdin will report an end of file condition and both cin and stdin will set their internal end of file flag. Then the call to cin.clear() clears the C++ stream flag but it is unspecified whether it has an action on the stdin object internal flag.

因此对C ++ cin 对象和C stdin 一个。

So you are responsable for the lack of synchronization between the C++ cin object and the C stdin one.

现在,详细了解从您的ideone复制的这段代码中发生的情况:

Now for the details on what happens in this code copied from your ideone:

#include <cstdio>
#include <iostream>

// first type the shortcut for EOF, then a single character

int main() {
    using namespace std;

    char ch;
    cin >> ch;             // 1

    cin.clear();           // 2

    cout << boolalpha      // 3
         << "feof(stdin): " << bool(feof(stdin)) << endl
         << "cin.eof(): " << cin.eof() << endl;

    ch = char(getchar());  // 4
    cout << ch << endl;    // 5

    cout << boolalpha      // 6
         << "feof(stdin): " << bool(feof(stdin)) << endl
         << "cin.eof(): " << cin.eof() << endl;
}

// 1:您从 cin看了一个字符(忽略字符):从 stdin stdin 内部读取的cin文件,设置其内部EOF标志,并将文件结束条件返回到 cin cin 设置自己的EOF标志

//1 : you read a char from cin (ignoring the char): cin internally read from stdin, stdin finds an end of file, sets its internal EOF flag and return an end of file condition to cin. cin sets its own EOF flag

// 2:清除的EOF标志cin stdin 不变(在此实现中,因为行为未由标准AFAIK指定)

//2 : you clear the EOF flag on cin, stdin is unchanged (in this implementation since behaviour is unspecified by standard AFAIK)

// 3:符合预期的 feof(stdin)是true,而 cin.eof()是false

//3 : as expected feof(stdin) is true and cin.eof() is false

// 4:您从 stdin cin 保持不变)。由于您已经在文件末尾,因此getchar返回整数常量EOF = -1。但是在您强制转换为char -1时会转换为'\xff',ASCII char DEL

//4 : you read a char from stdin (cin is untouched here). As you are already at end of file, getchar returns the integer constant EOF = -1. But as you force a conversion to char -1 is converted to '\xff', ASCII char DEL

// 5:'\xff'不是有效的UTF8序列,并且ideone将其显示为Unicode替换字符。

//5 : '\xff' is not a valid UTF8 sequence and ideone displays it as the unicode REPLACEMENT CHARACTER �

// 6: feof(stdin)仍然为true:C FILE已到达文件结尾,并且 cin.eof()仍然为假,因为自// 3

//6 : feof(stdin) is still true: the C FILE has reached end of file, and cin.eof() is still false because nothing changed it since //3

TL / DR之后,它什么都没有改变:一切都如预期:基础文件到达文件末尾,并且 getchar()确实返回EOF,并设置了eof标志。就像您显式清除 cin 标志并且以后不再使用它一样, cin.eof()是错误的。

TL/DR: everything is as expected: the underlying file as reached end of file and getchar() does return EOF, and the eof flags are set. Simply as you explicitely clear cin flags and never use it later cin.eof() is false.

这篇关于cin.eof()和feof(stdin)不一致的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆