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

2024-01-22 10:08

本文主要是介绍判断读入数据文件结尾【从文件读入数据】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

参考:http://blog.csdn.net/rebel_321/article/details/4927464

在使用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



这篇关于判断读入数据文件结尾【从文件读入数据】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/632649

相关文章

C++实现回文串判断的两种高效方法

《C++实现回文串判断的两种高效方法》文章介绍了两种判断回文串的方法:解法一通过创建新字符串来处理,解法二在原字符串上直接筛选判断,两种方法都使用了双指针法,文中通过代码示例讲解的非常详细,需要的朋友... 目录一、问题描述示例二、解法一:将字母数字连接到新的 string思路代码实现代码解释复杂度分析三、

MySQL InnoDB引擎ibdata文件损坏/删除后使用frm和ibd文件恢复数据

《MySQLInnoDB引擎ibdata文件损坏/删除后使用frm和ibd文件恢复数据》mysql的ibdata文件被误删、被恶意修改,没有从库和备份数据的情况下的数据恢复,不能保证数据库所有表数据... 参考:mysql Innodb表空间卸载、迁移、装载的使用方法注意!此方法只适用于innodb_fi

mysql通过frm和ibd文件恢复表_mysql5.7根据.frm和.ibd文件恢复表结构和数据

《mysql通过frm和ibd文件恢复表_mysql5.7根据.frm和.ibd文件恢复表结构和数据》文章主要介绍了如何从.frm和.ibd文件恢复MySQLInnoDB表结构和数据,需要的朋友可以参... 目录一、恢复表结构二、恢复表数据补充方法一、恢复表结构(从 .frm 文件)方法 1:使用 mysq

mysql8.0无备份通过idb文件恢复数据的方法、idb文件修复和tablespace id不一致处理

《mysql8.0无备份通过idb文件恢复数据的方法、idb文件修复和tablespaceid不一致处理》文章描述了公司服务器断电后数据库故障的过程,作者通过查看错误日志、重新初始化数据目录、恢复备... 周末突然接到一位一年多没联系的妹妹打来电话,“刘哥,快来救救我”,我脑海瞬间冒出妙瓦底,电信火苲马扁.

golang获取prometheus数据(prometheus/client_golang包)

《golang获取prometheus数据(prometheus/client_golang包)》本文主要介绍了使用Go语言的prometheus/client_golang包来获取Prometheu... 目录1. 创建链接1.1 语法1.2 完整示例2. 简单查询2.1 语法2.2 完整示例3. 范围值

javaScript在表单提交时获取表单数据的示例代码

《javaScript在表单提交时获取表单数据的示例代码》本文介绍了五种在JavaScript中获取表单数据的方法:使用FormData对象、手动提取表单数据、使用querySelector获取单个字... 方法 1:使用 FormData 对象FormData 是一个方便的内置对象,用于获取表单中的键值

Rust中的BoxT之堆上的数据与递归类型详解

《Rust中的BoxT之堆上的数据与递归类型详解》本文介绍了Rust中的BoxT类型,包括其在堆与栈之间的内存分配,性能优势,以及如何利用BoxT来实现递归类型和处理大小未知类型,通过BoxT,Rus... 目录1. Box<T> 的基础知识1.1 堆与栈的分工1.2 性能优势2.1 递归类型的问题2.2

Python使用Pandas对比两列数据取最大值的五种方法

《Python使用Pandas对比两列数据取最大值的五种方法》本文主要介绍使用Pandas对比两列数据取最大值的五种方法,包括使用max方法、apply方法结合lambda函数、函数、clip方法、w... 目录引言一、使用max方法二、使用apply方法结合lambda函数三、使用np.maximum函数

Java判断多个时间段是否重合的方法小结

《Java判断多个时间段是否重合的方法小结》这篇文章主要为大家详细介绍了Java中判断多个时间段是否重合的方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录判断多个时间段是否有间隔判断时间段集合是否与某时间段重合判断多个时间段是否有间隔实体类内容public class D

Redis的数据过期策略和数据淘汰策略

《Redis的数据过期策略和数据淘汰策略》本文主要介绍了Redis的数据过期策略和数据淘汰策略,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录一、数据过期策略1、惰性删除2、定期删除二、数据淘汰策略1、数据淘汰策略概念2、8种数据淘汰策略