IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> c++读取配置文件 -> 正文阅读

[C++知识库]c++读取配置文件

在实际开发中,程序读取配置文件以加载数据非常常见,如何安全高效地读取文件比较重要。本文代码来自于《c++新经典》。

?假设有一个txt格式的文件,里面记录了花里胡哨的内容,需要把这些内容一字不差地读取到程序中,应该如何用c++实现?

书中的代码如下:

#include <iostream>
using namespace std;
int main()
{
	//打开文件
	FILE* fp = nullptr;
	errno_t err;
	err = fopen_s(&fp, "config.txt", "r");
	if (!fp) {
		cout << "can not open file!" << endl;
	}
	//打开文件成功
	else {
		//定义存储每行字符串的数组
		char linebuff[1024];
		//没读到文件尾就一直执行
		while (!feof(fp))
		{
			linebuff[0] = 0;//给第一位置零
			//fgets函数功能为从指定的流中读取数据,每次读取一行。其原型为:char *fgets(char *str, int n, FILE *stream);
			//从指定的流 stream 读取一行,并把它存储在 str 所指向的字符串内。当读取 (n-1) 个字符时,或者读取到换行符时,或者到达文件末尾时,它会停止
			if (fgets(linebuff, sizeof(linebuff) - 1, fp) == nullptr)//如果读到文件尾或者没读到字符,跳出本次循环
				continue;
			if (linebuff[0] == '\0') {//如果数组第一位是零,说明没读到内容,则跳出本次循环
				continue;
			}
		lblprocstring:
			if (strlen(linebuff) > 0) {//如果行尾是换行(0X0A,10)或者换行(0X0D,13)就都截掉
				if (linebuff[strlen(linebuff) - 1] == 10 || linebuff[strlen(linebuff) - 1] == 13) {
					linebuff[strlen(linebuff) - 1] = 0;//截掉,注意strlen不计算句尾的0,sizeof会计算
					goto lblprocstring;
				}
			}
			if (strlen(linebuff) <= 0)//如果是个空行,跳出本次循环
				continue;
			printf("%s\n", linebuff);//打印一行
		}
		fclose(fp);
	}
	return 0;
}

结果如下图所示,已经完整地将配置文件的内容打印出来了。

?代码使用一个字符数组记录每行内容,为防止读取失败,代码中通过第一位清零并查询的方式检查:

            linebuff[0] = 0;//给第一位置零
			......
			if (linebuff[0] == '\0') {//如果数组第一位是零,说明没读到内容,则跳出本次循环
				continue;
			}

如果不需要代码非常严谨,可以将以上的内容从代码中删除。

读取一行文本的核心实现是以下代码:

            //fgets函数功能为从指定的流中读取数据,每次读取一行。其原型为:char *fgets(char *str, int n, FILE *stream);
			//从指定的流 stream 读取一行,并把它存储在 str 所指向的字符串内。当读取 (n-1) 个字符时,或者读取到换行符时,或者到达文件末尾时,它会停止
			if (fgets(linebuff, sizeof(linebuff) - 1, fp) == nullptr)//如果读到文件尾或者没读到字符,跳出本次循环
				continue;

fgets函数读取到内容后,会返回文件流指针fp。

fgets读取 (n-1) 个字符时,或者读取错误时,或者到达文件末尾时,会返回nullptr。在这个情况我们需要考虑该如何处理。

1.如果读取到了最大字符数量,但是仍旧没有读到换行符,说明该行的字符长度超过了数组设置的长度:这种情况下会返回一个不完整的行,并且在下一次会继续在该行进行字符读取。按照书中的设计思路,这种情况不应该出现,配置文件每行的最长长度应该有个明确的上限,该上限决定了字符数组的长度。

2.读取错误:这种情况下没别的可以做,应该采用continue跳过该次循环,进行重复读取 。

3.到达文件尾:这种情况下需要与情况2进行区分,因此循环应使用feof(fp)作为循环的判断依据,通过feof而不是fgets来判断文件是否读取完毕,既然这个任务交给feof去做了,那么这里依然采用continue跳过该次循环即可。

数组读取完数据之后需要对句尾进行裁剪,把回车符号都去掉:

            lblprocstring:
			if (strlen(linebuff) > 0) {//如果行尾是换行(0X0A,10)或者换行(0X0D,13)就都截掉
				if (linebuff[strlen(linebuff) - 1] == 10 || linebuff[strlen(linebuff) - 1] == 13) {
					linebuff[strlen(linebuff) - 1] = 0;//截掉,注意strlen不计算句尾的0,sizeof会计算
					goto lblprocstring;
				}
			}
			if (strlen(linebuff) <= 0)//如果是个空行,跳出本次循环
				continue;
			printf("%s\n", linebuff);//打印一行

这里采用了一个goto循环,在循环中不断地判断数组内数据的尾部是不是回车符或者换行符,若是的话便对该符号进行清零操作。注意这里使用strlen()-1来判断数据末尾的位置,这是因为strlen函数是自动无视掉字符串末尾的‘/0’的,而sizeof并不会,因此在这种末尾清零操作中必须使用strlen。

由于不习惯使用goto循环,我改成了while循环:

            while (strlen(linebuff)>0)
			{
				if (linebuff[strlen(linebuff) - 1] == 10 || linebuff[strlen(linebuff - 1)] == 13) {
					linebuff[strlen(linebuff) - 1] = 0;
				}
				else {
					break;
				}
			}

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-06-26 16:45:42  更:2022-06-26 16:46:08 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/12 4:56:09-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码