ifstream的eof()如何工作?
#include <iostream> #include <fstream> int main() { std::fstream inf( "ex.txt", std::ios::in ); while( !inf.eof() ) { std::cout << inf.get() << "\n"; } inf.close(); inf.clear(); inf.open( "ex.txt", std::ios::in ); char c; while( inf >> c ) { std::cout << c << "\n"; } return 0; }
我真的很困惑eof()
函数。 假设我的ex.txt的内容是:
abc
它总是读取一个额外的字符,并使用eof()
读取时显示-1
。 但inf >> c
给出了正确的输出是'abc'? 任何人都可以帮我解释一下吗?
-1就是说你已经到达文件的末尾了。 比较它使用std::char_traits<char>::eof()
(或std::istream::traits_type::eof()
) – 避免-1,这是一个幻数。 (尽pipe另一个有点冗长 – 你总是可以调用istream::eof
)
EOF标志只有在读取试图读取文件末尾时才被设置。 如果我有一个3字节的文件,而我只读了3个字节,EOF是false
,因为我还没有尝试读过文件的末尾。 虽然这对于通常知道它们的大小的文件来说似乎很困惑,但是直到在一些设备(例如pipe道和networking套接字)上尝试读取之后才知道EOF。
第二个例子的工作原理是: inf >> foo
将总是返回inf
,带有尝试读取并将其存储在foo
的副作用。 inf
,在if
或while
,如果文件是“好的”,则评估为true
:没有错误,没有EOF。 因此,当读取失败时, inf
会变成false
,并且你的循环正确地中止。 但是,采取这个常见的错误:
while(!inf.eof()) // EOF is false here { inf >> x; // read fails, EOF becomes true, x is not set // use x // we use x, despite our read failing. }
但是,这个:
while(inf >> x) // Attempt read into x, return false if it fails { // will only be entered if read succeeded. }
这是我们想要的。
iostream不知道它在文件的末尾,直到它试图读取文件末尾的第一个字符。
在cplusplus.com的示例代码说这样做:(但是你不应该这样做)
while (is.good()) // loop while extraction from file is possible { c = is.get(); // get character from file if (is.good()) cout << c; }
更好的习惯是将读取操作移动到循环条件中,如下所示:(您可以使用所有返回*this
istream
读取操作(包括>>
操作符)
char c; while(is.get(c)) cout << c;
EOF标志只在读取操作尝试读取文件结尾之后才被设置。 get()
返回符号常量traits::eof()
(它恰好等于-1),因为它到达了文件的末尾,并且不能再读取任何数据,只有在那时eof()
为真。 如果你想检查这种情况,你可以做如下的事情:
int ch; while ((ch = inf.get()) != EOF) { std::cout << static_cast<char>(ch) << "\n"; }
eof()检查stream状态下的eofbit。
在每个读取操作中,如果位置在stream的末尾并且需要读取更多数据,则eofbit设置为true。 因此,在获得eofbit = 1之前,你会得到一个额外的字符。
正确的方法是在读操作后检查eof是否到达(或读操作是否成功)。 这是你的第二个版本 – 你做一个读取操作,然后使用生成的stream对象引用(这将返回)作为布尔值,这导致检查fail()。