c++使用eof()最后一个字符读取两遍

先让我们看这样的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include<iostream>
#include<string>
#include<stdio.h>
#include<queue>
#include <cstdio>
#include<string.h>
#include <fstream>
#include<cstdlib>
#include<iomanip>
#include<algorithm>
#include<cmath>

using namespace std;


int main()
{
char a;
ifstream file;
file.open("test.txt");
if (!file.is_open())
{
cout << "error"<<endl;
exit(1);
}
while (!file.eof())
{
file >> a;
cout << a;
}
return 0;
}

test.txt文件内容为12345
可输出的结果却是
123455
为什么会出现这样的情况呢?

eof函数是在eofbit error state flag设为true时才返回1,而读取到’5’的时候eofbit error state flag仍然是flase,只有读取到’5’后面的文件结束符0xff时eof函数才会返回1,所以会多读取一次,而读取文件结束符并不会改变a的值,所以会多输出一次5。

解决办法时在这种情况下不要使用eof(),而是把file>>a作为while的判断条件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include<iostream>
#include<string>
#include<stdio.h>
#include<queue>
#include <cstdio>
#include<string.h>
#include <fstream>
#include<cstdlib>
#include<iomanip>
#include<algorithm>
#include<cmath>

using namespace std;

int main()
{
char a;
ifstream file;
file.open("test.txt");
if (!file.is_open())
{
cout << "error"<<endl;
exit(1);
}
while (file >> a)
cout << a;
return 0;
}

这样就没问题了.

奇怪的是,如果a不是char,而是其他类型的变量,使用eof()就不会出现这样的问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int main()
{
int a;
ifstream file;
file.open("test.txt");
if (!file.is_open())
{
cout << "error"<<endl;
exit(1);
}
while (!file.eof())
{
file >> a;
cout << a;
}
return 0;
}

这样的结果也是12345,原因暂时不知道…

还有就是,不应该用eof()来判断文件是否为空

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int main()
{
char a='1';
ifstream file;
file.open("test.txt");
if (!file.is_open())
{
cout << "error"<<endl;
exit(1);
}

if (file.eof())
{
cout << "file is empty." << endl;
return 0;
}

while (!file.eof())
{
file >> a;
cout << a;
}
return 0;
}

如果test.txt存在但为空的话,结果会是1,因为这里没有对文件进行读取,所以eofbit error state flag并没有被设为true
如果要判断文件是否为空的话,应该使用peek()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int main()
{
char a='1';
ifstream file;
file.open("test.txt");
if (!file.is_open())
{
cout << "error"<<endl;
exit(1);
}

if (file.peek()==EOF)
{
cout << "file is empty." << endl;
return 0;
}

while (!file.eof())
{
file >> a;
cout << a;
}
return 0;
}

这样就没问题了