我们在读取文件时,书中经常提到的逻辑是这样的,但这是错误的!
while(!feof(Fp))
{
fgets(readLine,10000,Fp);
//do something.
}
原因在于feof()只有在你尝试读取文件结尾之后,才会返回true。也就是说,feof()之解释上次文件读写是否到达结尾,而不是下一次。
所以正确的逻辑应该是这样的。
while(true) {
fgets(readLine,10000,Fp);
if( feof(Fp) ) break;
do something.
}
发信站: 北邮人论坛 (Thu Dec 2 18:02:45 2010), 站内
【 在 RaulSpain007 的大作中提到: 】
bool Token()
{
ifstream in;
string token;
in.open("Token.txt", ios::in);
if(in.good())
{
while(!in.eof()) //这里有问题,如果最后一个7后面有个空格或回车什么的,读完最后一个7的时候,就不会到eof
{
in >> token; //这时候,读取操作俨然失败,因为7后面没有数了,于是token保持上次值不变,仍然为7
TokenVector.push_back(token); //于是7就又一次被加到vector中了
}
in.close();
return true;
}
else
cout << "Can't find Token.txt." << endl;
return false;
}
解决办法:
bool Token()
{
ifstream in;
string token;
in.open("Token.txt", ios::in);
if(in.good())
{
while(in >> token) //这句话等价于:while(in>>token, in)
//而C++标准规定,stream类型能够强制转化为void*类型,
//(void*)(stream)的值为:stream.fail() ? 0值 : 非0值。
//所以上面的语句又间接等价于:while(in>>token,!in.fail())
{
TokenVector.push_back(token);
}
in.close();
return true;
}
else
cout << "Can't find Token.txt." << endl;
return false;
}
请注意,下面的代码是错的:
bool Token()
{
ifstream in;
string token;
in.open("Token.txt", ios::in);
if(in.good())
{
while(!in.fail()) //第一次读完7后,读取操作成功,fail()为假,继续循环
{
in >> token; //此时,读取操作失败,token不变,仍为上一个7
TokenVector.push_back(token); //这个7就又被哀怨地加到vector中了!
}
in.close();
return true;
}
else
cout << "Can't find Token.txt." << endl;
return false;
}
使用流的一个经验是,要在读取操作之后立即判断是否成功,成功则读取数据有效,不成功则读取数据无效。
上面的解决办法便是遵守了这条规则。