cin.eof()和feof(stdin)不一致 [英] cin.eof() and feof(stdin) are discordant
问题描述
可以 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 $ c $有作用。 c>对象内部标志。
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 $ c>对象和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屋!