#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;
}
Run Code Online (Sandbox Code Playgroud)
我真的很困惑eof()
功能.假设我的ex.txt的内容是:
abc
Run Code Online (Sandbox Code Playgroud)
它总是读取一个额外的字符,并-1
在阅读时显示eof()
.但是inf >> c
给出了'abc'的正确输出?任何人都可以帮我解释一下吗?
Tha*_*tos 69
-1是get
说你到达文件末尾的方式.使用std::char_traits<char>::eof()
(或std::istream::traits_type::eof()
)比较- 避免-1,这是一个神奇的数字.(虽然另一个有点冗长 - 你总是可以打电话istream::eof
)
EOF标志仅在读取尝试读取超过文件末尾时设置.如果我有一个3字节的文件,而我只读取3个字节,那么EOF就是false
,因为我还没有尝试读过文件的末尾.虽然这对于通常知道其大小的文件而言似乎令人困惑,但在某些设备(例如管道和网络套接字)上尝试读取之前,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.
}
Run Code Online (Sandbox Code Playgroud)
但是,这个:
while(inf >> x) // Attempt read into x, return false if it fails
{
// will only be entered if read succeeded.
}
Run Code Online (Sandbox Code Playgroud)
这就是我们想要的.
EOF标志仅在读取操作尝试读取超过文件末尾后设置.get()
返回符号常量traits::eof()
(恰好等于-1),因为它到达文件的末尾并且无法读取更多数据,并且只有在那一点才会eof()
成立.如果要检查此条件,可以执行以下操作:
int ch;
while ((ch = inf.get()) != EOF) {
std::cout << static_cast<char>(ch) << "\n";
}
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
更好的习惯用法是将读取移动到循环条件中,如下所示:(您可以对返回的所有 istream
读取操作执行此操作*this
,包括>>
操作符)
char c;
while(is.get(c))
cout << c;
Run Code Online (Sandbox Code Playgroud)