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?
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;
}
Output:
feof(stdin): true
cin.eof(): false
Well, there is no surprise here.
std::cin
is truely defined in the C++ library, butstdin
is defined in the C standard library that is member of the C++ one mainly for compatibility reasons.Draft n4659 for C++17 says:
and later:
That means that
cin
is a C++ stream wrapping the underlyingstdin
C FILE object. As a result, when you try to read a character fromcin
after reaching the end of file,cin
will ask it fromstdin
,stdin
will report an end of file condition and bothcin
andstdin
will set their internal end of file flag. Then the call tocin.clear()
clears the C++ stream flag but it is unspecified whether it has an action on thestdin
object internal flag.So you are responsable for the lack of synchronization between the C++
cin
object and the Cstdin
one.Now for the details on what happens in this code copied from your ideone:
//1 : you read a char from
cin
(ignoring the char): cin internally read fromstdin
,stdin
finds an end of file, sets its internal EOF flag and return an end of file condition tocin
.cin
sets its own EOF flag//2 : you clear the EOF flag on
cin
,stdin
is unchanged (in this implementation since behaviour is unspecified by standard AFAIK)//3 : as expected
feof(stdin)
is true andcin.eof()
is false//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'
is not a valid UTF8 sequence and ideone displays it as the unicode REPLACEMENT CHARACTER �//6 :
feof(stdin)
is still true: the C FILE has reached end of file, andcin.eof()
is still false because nothing changed it since //3TL/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 clearcin
flags and never use it latercin.eof()
is false.