C++ ifstream';什么是eof()工作?
当使用C++ ifstream';什么是eof()工作?,c++,ifstream,eof,C++,Ifstream,Eof,当使用eof()进行读取时,它总是读取额外的字符并显示-1。但是inf>>c给出了正确的输出,即“abc”?有人能帮我解释一下吗?只有在读取操作试图读取超过文件末尾的内容后,才会设置EOF标志get()正在返回符号常量traits::eof()(恰好等于-1),因为它到达了文件末尾,无法读取更多数据,只有在该点上,eof()才会为真。如果要检查此情况,可以执行以下操作: abc intch; 而((ch=inf.get())!=EOF){ iostream不知道它在文件末尾,直到它试图读取文件
eof()
进行读取时,它总是读取额外的字符并显示-1
。但是inf>>c
给出了正确的输出,即“abc”?有人能帮我解释一下吗?只有在读取操作试图读取超过文件末尾的内容后,才会设置EOF标志get()
正在返回符号常量traits::eof()
(恰好等于-1),因为它到达了文件末尾,无法读取更多数据,只有在该点上,eof()
才会为真。如果要检查此情况,可以执行以下操作:
abc
intch;
而((ch=inf.get())!=EOF){
iostream不知道它在文件末尾,直到它试图读取文件末尾的第一个字符
老师说要这样做:(但实际上你不应该这样做)
eof()检查处于流状态的eofbit
在每次读取操作中,如果位置在流的末尾,并且必须读取更多数据,则eofbit设置为true。因此,在获得eofbit=1之前,您将获得一个额外字符
正确的方法是在读取操作后检查是否达到eof(或读取操作是否成功)。这是第二个版本所做的操作-执行读取操作,然后将生成的流对象引用(它>>返回)用作布尔值,这将导致检查失败().-1是get
表示您已到达文件末尾的方式。使用std::char\u traits::eof()
(或std::istream::traits\u type::eof()
)-avoid-1,这是一个神奇的数字。(尽管另一个有点冗长,但您始终可以调用istream::eof
)
EOF标志仅在读取尝试读取超过文件结尾时设置。如果我有一个3字节的文件,并且我只读取了3个字节,则EOF为false
,因为我还没有尝试读取超过文件结尾。虽然这对于通常知道其大小的文件来说似乎很混乱,但只有在某些设备上尝试读取时,EOF才知道,例如管道和网络插座
第二个示例的作用是inf>>foo
将始终返回inf
,其副作用是尝试读取某些内容并将其存储在foo
中,如果文件“良好”,则在if
或while
中,将评估为true
:无错误,无EOF。因此,当读取失败时,inf
将计算为false
,循环将正确中止。但是,请注意以下常见错误:
char c;
while(is.get(c))
cout << c;
然而,这:
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.
}
这正是我们想要的。“只有在读取操作到达文件末尾后,才会设置EOF标志。”正是导致对EOF产生混淆的语句。EOF标志仅在读取操作尝试读取超过文件结尾后设置。最后一位非常关键:如果我从一个3字节长的文件中读取3个字节,EOF为false,直到我尝试另一次读取。iostream不会返回EOF常量。int istream::get()的返回值
文件末尾似乎没有定义——你必须检查istream::eof()
@Ken Bloom:你确定吗?我的标准是“Returns:c
如果可用,否则traits::eof()
”27.6.1.3(草案2,1996年12月2日)你是对的,但这与C stdio使用的EOF
常量相差甚远。我错了。在char\u traits
的定义中,它说char\u traits::EOF()
返回EOF
@Martin York EOF标志可能没有设置,但get()
仍将返回traits::EOF()
,如果读取失败,它会被用作一般错误代码。应该“是流
读取操作…包括
操作符”?@Thanatos:是的。这就是我在深夜发布的内容。你想要!is.fail()
而不是is.good()
。当从文件中读取(例如)一个数字时,流必须到达文件末尾,然后才能确定是否读取该数字的最后一位。在这种情况下,将成功读取一个数字,但将到达文件末尾,从而导致is.good()
返回false。这可能会导致您跳过文件上的最后一个值。相反,检查!is.fail()
在所有情况下都是正确的。@KenBloom-如果while(is.get(c))中的流是二进制的,如果字节值为0(二进制文件的完全期望值),这不会过早终止循环吗使用while(n=is.get()!=Traits::eof())不是更好吗对于二进制文件?@smgreenfield:get的重载包含一个输出参数,返回一个istream&用于进一步链接或错误报告。感谢您指出这一点。我在TopCoder上竞争,为了节省时间,我通常导入所有名称空间。感谢Thanatos。我想我现在就明白了;)可能不应该使用>>而不是get()。请记住>>运算符在尝试读取下一个值之前总是跳过空格,而get()一次读取每个字符。@Thanatos:很抱歉打扰您,但是…流呢?您说过当我们尝试读取超过文件结尾的字符时会设置EOF,但是当我们尝试peek()时会发生什么情况
在没有字符的输入流cin
中?标准规定调用traits::eof()
,但调用peek()当我尝试这样使用它时,它似乎在等待输入。peek
如果您尝试查看输入的结尾,它将返回EOF。但是,cin
通常是您正在键入的终端。(这似乎是您的情况。)“等待用户输入”与EOF不同,它只是数据源(您)速度很慢。所以peek
阻塞,等待您输入。如果
while (is.good()) // loop while extraction from file is possible
{
c = is.get(); // get character from file
if (is.good())
cout << c;
}
char c;
while(is.get(c))
cout << c;
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.
}