feof(stdin)和cin.eof()会产生不一致的结果吗?我希望他们不会这样做,但我猜我遗漏了一些东西。标准对此有什么规定吗?
考虑下面的例子,当没有输入的时候。这可以通过在终端中输入EOF的快捷键,或者通过在/dev/null (Unix)上重定向输入,或者在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发布于 2018-04-17 22:56:01
好吧,这没什么好惊讶的。
std::cin实际上是在C++库中定义的,但是stdin是在C标准库中定义的,C标准库是C++的成员,主要是出于兼容性的原因。
C++17的草案n4659说:
30.4.3 窄流对象 [narrow.stream.objects] istream cin; 1 对象 cin 控制来自与 (30.11.1) 中声明的对象
stdin关联的流缓冲区的输入。
之后的版本:
30.11 C 库文件 [c.files] 30.11.1 标题
<cstdio>概要 [cstdio.syn] ... 1 头文件<cstdio>的内容和含义与C标准库头文件<stdio.h>相同。
这意味着cin是一个包装底层stdin C文件对象的C++流。因此,当您在到达文件结尾后尝试从 cin读取字符时,cin将从stdin请求它,stdin将报告文件结束状态,并且cin和stdin都将设置其内部文件结束标志。然后,对cin.clear()的调用将清除C++流标志,但未指定它是否对stdin对象内部标志进行了操作。
所以你要为C++ cin对象和C stdin对象之间缺乏同步负责。
现在要详细了解从您的想法中复制的代码中发生了什么:
#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读取字符(忽略字符):cin从stdin内部读取,stdin找到文件结尾,设置其内部EOF标志,并将文件结束条件返回给cin。cin设置自己的EOF标志
//2 :清除cin上的EOF标志,stdin保持不变(在此实现中,因为标准AFAIK未指定行为)
//3 :不出所料,feof(stdin)为真,cin.eof()为假
//4 :您从stdin读取了一个字符(此处未涉及cin)。由于您已经在文件的末尾,getchar返回整数常量EOF = -1。但是,当您强制转换为char -1并转换为'\xff'时,ASCII char DEL
//5:'\xff'不是有效的UTF8序列,并且ideone将其显示为unicode替换字符�
//6:feof(stdin)仍然为true: C文件已经到达文件末尾,cin.eof()仍然为false,因为//3之后没有任何更改
TL/DR:一切都符合预期:底层文件到达文件末尾,getchar()返回EOF,并且设置了eof标志。简单地说,cin.eof()是假的,因为您显式地清除了cin标志,并且以后永远不会使用它。
https://stackoverflow.com/questions/49880746
复制相似问题