C++eof()判断是否读取到文件尾

概述

eof()函数是一种我们常用的判断是否读取到文件尾的类方法。
eof()函数的返回值是 bool 值。这也说明eof()函数封装的很彻底,我们无法对eof()的返回值做文章,除了简单的判断。如果读到文件尾则返回真,否则返回假。
这样来看,eof()十分简单,无非就是判断。如果返回真,说明结束了,然后结束读取即可。但是,eof函数有一点奇怪,如果你这样想,那么eof函数可能和你想的有点出入。
让我们来简单测试一下。

测试eof()函数

//读取eof_test.txt, 文件内容如下:
// 12
// 34
# include <iostream>
# include <fstream>
# include <string>

int main()
{
	std::string file = "./eof_test.txt";			// 读取的文件路径
	std::ifstream ifs;								// 创建文件读取对象
	ifs.open(file.c_str(), std::ios::in);			// 读取模式ios::in
	if(!ifs.is_open()){								//判断文件是否能正常打开
		std::cout << "Input.txt open failed!" << std::endl;
		return -1;
	}
	
	char ch;
	while (!ifs.eof()) {							//读取文件,输出
		ifs.get(ch);								//一次读取一个字符
		std::cout << ch;							//输出字符
	}
	
	ifs.close();									//关闭资源文件
	return 0;
}

输出结果:
在这里插入图片描述
简单分析:

为什么原文件时12\n34, 而结果是12\n344?
首先,说明了while循环没有及时结束,不然不会多输出一个4的,那这显然和eof()函数脱不了关系。eof()不会如我们所想的,读完文件立刻返回真,而是有延迟,延迟了一个字符。

为什么多输出的是4,而不是其他字符呢?
首先,我们都知道文件有文件结束符,具体是什么,我们先不谈。反正,我们肯定知道,文件的结束读取,肯定和文件结束符息息相关。那简单了,eof之所以有延迟了一个字符,很可能就是因为读取了文件结束符,读取完文件结束符之后,才能判断文件已经读取完毕了。这样理解,我认为是可以接受的,但eof()内部具体是什么样,我借助vs2022看了eof()源码,但是没看出什么。

文件结束符是什么呢?我们能否借助C++把他输出来看看呢?
依据上面的理解,ifs.get(ch)语句在最后一次会读到文件结束符。但最后输出的文件结束符是4,显然文件结束符不可能是4,这是否就说明,上面我的的理解就有问题呢?其实呢,这并不冲突。有一种可能,那就是虽然读到文件结束符了,但并没有放到ch变量中,所有变量ch值并没有改变,仍然是4。简单测试一下。

//将以上代码
//while (!ifs.eof()) {								//读取文件,输出
//		ifs.get(ch);								//一次读取一个字符
//		std::cout << ch;							//输出字符
}
//替换成
while (!ifs.eof()) {								//读取文件,输出
		ifs.get(ch);								//一次读取一个字符
		std::cout << ch;							//输出字符
		ch = '#';									//将ch用字符'#'做伪清空
}

//运行结果
//12
//34#

看运行结果,可以说明我们上述的分析是可以说的通的。
程序可能确实读到文件结束符了,但出于某种原因,又给丢弃了。所以可以说,可能有读取文件结束符的过程,但没有读取的结果,读取文件结束符并不会覆盖上次读取的结果,所以也就解释了最初的12\n34变成12\n344。
知道这个,我们就可以对最初的代码,进行一定的修改,使之能输出正确的结果。

代码改进

// 改进1
# include <iostream>
# include <fstream>
# include <string>

int main()
{
	std::string file = "./eof_test.txt";
	std::ifstream ifs;
	ifs.open(file.c_str(), std::ios::in);
	if (!ifs.is_open()) {
		std::cout << "Input.txt open failed!" << std::endl;
		return -1;
	}
	std::string str = "";
	char ch;

	while (!ifs.eof()) {
		ifs.get(ch);
		std::cout << ch;
		ch = ' ';				//唯一修改点,增加此语句。
	}

	ifs.close();
	return 0;
}

//输出结果 
//12
//34

虽然结果看起来和原文件一样,但我们必须明确最后4后面是有个空格的,只是看不出吧。
这就埋了个雷,我们可能会倒在这个不起眼的空格上,那我们有没有彻底解决的方案呢?自然是有的,如下:

// 改进2
# include <iostream>
# include <fstream>
# include <string>

int main()
{
	std::string file = "./eof_test.txt";
	std::ifstream ifs;
	ifs.open(file.c_str(), std::ios::in);
	if (!ifs.is_open()) {
		std::cout << "Input.txt open failed!" << std::endl;
		return -1;
	}
	std::string str = "";
	char ch;

	ifs.get(ch);			//增加语句
	while (!ifs.eof()) {
		std::cout << ch;	//和ifs.get(ch);	交换位置
		ifs.get(ch);		//和std::cout << ch;交换了位置
	}

	ifs.close();
	return 0;
}
  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值