while(f) 没有按预期表现

while(f) not behaving as expected

我在代码块中遇到此 C++ 代码的问题... 这是代码:

#include<iostream>
#include<fstream>
using namespace std;

class test {
   int i;
   float j;
public:
   void getdata() {
       std::cout<<"\nenter i and j:";
       std::cin>>i>>j;
   }
   void putdata() {
       std::cout<<"\ni="<<i<<"\tj="<<j;
   }
};
int main()
{
    test ob,ob1;
    fstream f;
    f.open("dil.txt",ios::out|ios::binary);
    for(int i=0;i<5;i++)
    {
       ob.getdata();
       f.write((char *)& ob,sizeof(ob));
    }
    f.close();
    f.open("dil.txt",ios::in|ios::binary);
    f.seekg(0);
    while(f) {
       f.read((char *)& ob1,sizeof(ob1));
       ob1.putdata();
    }
    f.close();
    return 0;
}

输入详情后的输出来了:

i=2     j=2.3
i=3     j=3.4
i=4     j=4.5
i=5     j=5.6
i=6     j=6.7
i=6     j=6.7

所以,我的问题是为什么最后一条语句会重复?...请帮忙

因为f只有在read() will fail due to the eof之后才会被设置为false。

试试这个方法:

while(f.read((char *)& ob1,sizeof(ob1))) {
    ob1.putdata();
}

这是因为你在输出数据之前你必须控制如果'f'读取OEF 喜欢这个代码:

#include<iostream>
#include<fstream>
using namespace std;
class test
{int i;float j;
public:
void getdata()
{std::cout<<"\nenter i and j:";
 std::cin>>i>>j;}
void putdata()
{std::cout<<"\ni="<<i<<"\tj="<<j;}
};
int main()
{test ob,ob1;
fstream f;
f.open("dil.txt",ios::out|ios::binary);
for(int i=0;i<5;i++)
{   ob.getdata();
    f.write((char *)& ob,sizeof(ob));
}
f.close();
f.open("dil.txt",ios::in|ios::binary);
f.seekg(0);
while(!f.eof())
{
    f.read((char *)& ob1,sizeof(ob1));
    if(!f.eof())
    {
        ob1.putdata();
    }
}
f.close();
return 0;}

代码 while(f) 通过在 f 上调用 std::basic_ios::operator bool 隐式地将 f 转换为 bool

在这种情况下 operator bool 将 return true 只要读取该流没有错误。

当您的代码到达文件末尾时,循环测试将调用 operator bool 并且它将 return true 因为到目前为止,没有错误。然后它调用 f.read 触发错误,因为它试图读取文件末尾。

由于流现在处于错误状态,f.read 将不会更新传递给它的缓冲区,因此缓冲区仍将具有上次调用中 return 编辑的数据。这就是重复最后一个值的原因。

现在,再次执行循环测试时,operator bool将return false,因为流处于错误状态,循环将终止。

我在初学者 C++ 代码中看到这个错误很多。在了解 iostreams 的工作原理之前,我一直在做同样的事情。我认为当某人来自一种语言时,这种情况往往会发生,在这种语言中,在阅读之前习惯于测试某种文件结束函数。大多数时候,我看到 iostream 的 eof 函数被用作循环测试。这会导致同样的问题,因为 eof 不会告诉您您已经到达流的末尾。它告诉您您已尝试阅读它。

C++ iostream 的设计使您可以对读取操作的结果进行循环测试。