Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/136.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ ifstream';什么是eof()工作?_C++_Ifstream_Eof - Fatal编程技术网

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.
}