您的位置:首页 > 其它

判断读入数据文件结尾【从文件读入数据】

2014-12-30 10:00 253 查看
参考:/article/11191090.html

在使用C/C++读文件的时候,使用eof()这个函数来判断文件是否为空或者是否读到文件结尾的时候会有一些特殊情况:

先看代码:

#include <iostream>
#include <fstream>
using namespace std;
int main()
{
char ch = 'x';
ifstream fin("test.txt" /*, ios::binary*/);
if (fin.eof())
{
cout << "file is empty."<<endl;
return 0;
}
while (!fin.eof())
{
fin.get(ch);
cout << ch;
}
return 0;
}


编译并运行,

1、如果test.txt不存在,程序会形成死循环,fin.eof()永远返回false,

2、如果test.txt为空,程序打印出一个x字符,

3、当test.txt中存在一字符串“abcd”且没有换行时,程序打印出“abcdd”,

4、当存在以上字符串并且有一新的空行时,程序打印出“abcd”加上一空行。

在这里,可能有一个误区,认为eof()返回true时是读到文件的最后一个字符,其实不然,eof()返回true时是读到文件结束符0xFF,而文件结束符是最后一个字符的下一个字符。

如下图所示:





因此,当读到最后一个字符时,程序会多读一次(编译器会让指针停留在最后一个字符那里,然后重复读取一次;因此当存在字符串且最后无换行的时候最后一个字符会读取两次并输出两次)

要解决以上的问题,只需要调整一下条件语句即可:

fin.peek() == EOF 或 fin.get(ch)

再来看一下另外一种情况:

#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
string str;
ifstream fin("test.txt"/*, ios::binary*/);
if (fin.peek() == EOF)
{
cout << "file is empty."<<endl;
return 0;
}
while (!fin.eof())
{
fin >> str;
cout << str;
}
e");
return 0;
}


上述代码在VS2012下编译运行,发现,当文件结尾没有空行时,结果正确;

当结尾有空行时,整个字符串将被重复输出一次,

若将条件语句修改为:

fin >> str

则结果正确

综上所述,

1. 判断文件是否为空时使用peek函数,若peek返回EOF则文件为空;

2. 读取文件过程中,读取非char型时,使用peek判断文件尾将不再适用,循环判断条件应改用>>操作符进行读取,若读入char型缓冲区,peek函数会表现得很好。
另外,其实类似与第二个方法,当做ACM之类的训练题需要为了方便读入数据自己建立文件存储数据时,还有一个更直接的常用方法(虽然不是最优→_→),就是当需要读入数据的时候,直接将读入的数据作为判断条件。
例如,输入数据第一行为数据个数,第二行为数据,此时可直接将第一行作为循环读入次数
测试程序:

#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
int main()
{
int n,i = 0;
ifstream cin("test.txt");
cin>>n;

while( n != -1 )
{
cout<<n<<endl;
vector<char> a(n);
while(n--)
{
cin>>a[i];
i++;
}

//输出读入结果作测试
for(i =0; i < a.size(); i++)
cout<<a[i];
cout<<endl<<"success"<<endl<<endl;//输出结果

i = 0;
cin>>n;
}

return 0;
}
在cpp根目录建立a.txt,内容如下(随意)
3
21a
5
1sd45
9
985sdf#%6
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: