c++读取cfg文件

参考:https://www.cnblogs.com/zhuzhenwei918/p/8569160.html

          四个文件 get_cfg.h,get_cfg.cpp,read_cfg.cpp,config.cfg

1.get_cfg.h


/*
这里 #define COMMENT '#'是宏定义的方式,易于扩展和重构,增加程序的效率;
下面的两句定义了两个函数,一个是读取配置信息的函数,
	另外一个是打印所有配置信息的函数,实参中的 & 是引用,这样就不是简单的赋值,而是修改实参同时也在修改传递进来的值。

使用COMMENT_CHAR更为清晰易懂一些。
这里定义了一些主要的函数,是为了在main.cpp使用,而get_cfg.cpp中的其他函数都是实现,而非接口。

*/


#ifndef __GET_CONFIG_H__
#define __GET_CONFIG_H__


#include <string>
#include <map>
#include <iostream>
using namespace std;

#define COMMENT_CHAR '#'

bool ReadConfig(const string & filename, map <string, string> & m);
void PrintConfig(const map<string, string> & m);
void FindInConfig(map<string, string> m, string key);

#endif //

2.get_cfg.cpp

#include "get_cfg.h"

#include <fstream>
#include <iostream>

using namespace std;
/*desc:
这里通过map实现了cfg文件中kv对的存取,方便操作。
注意这里的文件读取的操作,已经getline等相关函数。
注意整体的逻辑: 打开文件、从上到下获取行、注释忽略、建立map、存取kv对,这样,我们就可以得到cfg文件中所有有用的参数了。
最后FindInConfig函数中,我们将找到的kv输出,当然,在使用过程中,我们可以直接获取进行进一步的计算工作。
*/

bool IsSpace(char c)
{
	if (c == ' ' || c == '\t')
	{
		return true;
	}
	else
	{
		return false;
	}
}

bool IsCommentChar(char c)
{
	if (c == COMMENT_CHAR)
	{
		return true;
	}
	else
	{
		return false;
	}
}

// trim函数的作用是把一个字符串左边和右边的空格去掉,即为trim
void Trim(string & str) // 引用传参,这样在函数中修改该参数也会修改相应的变量
{
	if (str.empty())
	{
		return;
	}
	int i, start_pos, end_pos;
	for (i = 0; i < str.size(); i++)
	{
		if (!IsSpace(str[i]))
		{
			break;//跳出
		}
	}
	if (i == str.size())//如果该行全是空格,则该行最后一个字符为"\n",此时i == str.size()
	{
		str = "";
		return;
	}
	start_pos = i; // 获取到非空格的初始位置

	for (i = str.size() - 1; i >= 0; i--)
	{
		if (!IsSpace(str[i]))
		{
			break;
		}
	}
	end_pos = i;
	str = str.substr(start_pos, end_pos - start_pos + 1);
}

bool AnalyseLine(const string & line, string & key, string & value) // 分析一行,如果是注释行,则不处理,如果是k-v行,则提取出key-value值。
{
	if (line.empty())
	{
		return false;
	}
	int start_pos = 0, end_pos = line.size() - 1, pos;
	if ((pos = line.find(COMMENT_CHAR)) != -1)
	{
		if (0 == pos)
		{
			return false; // 如果一行的开头是#,说明是注释,则 不需要
		}
		end_pos = pos - 1; // 可能是注释在k-v后的情况
	}
	string new_line = line.substr(start_pos, end_pos - start_pos + 1); // 删掉后半部分的注释 FIX_ME: 这里应该是减错了吧
	// 下面pos的赋值时必要的,这样,就可在后面得到Key和value值了。
	if ((pos = new_line.find("=")) == -1) //说明前面没有 = 号
	{
		return false;
	}
	key = new_line.substr(0, pos); // 获得key
	value = new_line.substr(pos + 1, end_pos + 1 - (pos + 1)); // 获得value
	Trim(key);
	if (key.empty())
	{
		return false;
	}
	Trim(value); // 因为这里的key和value都是引用传递,可以直接被修改,所以不用返回
	return true;
}


// 读取一个cfg文件并保存到map中,map中的key和value都是string类型的。
bool ReadConfig(const string & filename, map<string, string> & m)
{
	m.clear(); // 删除map容器中的所有k-v对
	ifstream infile(filename.c_str());
	if (!infile)
	{
		cout << "file open failed!" << endl; // 文件打开失败,返回错误信息。
		return false;
	}
	string line, key, value; // 为了后续保存kv对
	while (getline(infile, line))
	{
		if (AnalyseLine(line, key, value))
		{
			m[key] = value; // 保存到map容器中的方法。
		}
	}
	infile.close(); // 当读取完之后,就要关闭这个文件。
	return true;
}

void PrintConfig(const map<string, string> & m)
{
	map<string, string>::const_iterator mite;
	for (mite = m.begin(); mite != m.end(); mite++)
	{
		cout << mite->first << "=" << mite->second << endl;
	}
}

void FindInConfig(map<string, string>  m, string  key) // 注意:之前用的一直都是string类型,所以这里用的也是string key,而不是char key。
{
	map<string, string>::iterator it;
	it = m.find(key);
	if (it == m.end())
	{
		cout << "there is no " << key << endl;
	}
	else
	{
		cout << it->second << endl;
	}
}

3. read_cfg.cpp


#include "get_cfg.h"

void read_cfg_test1()
{
	map<string, string> m;
	/*ReadConfig("C:\\Users\\Administrator\\Desktop\\readConfig\\readConfig\\config.cfg", m);*/
	ReadConfig("config.cfg", m);
	PrintConfig(m);
	string key;
	cout << "Please input a key to find the value in config.cfg" << endl;
	cin >> key;
	FindInConfig(m, key);
}


int main()
{
	read_cfg_test1();
	system("pause");
	return 0;
}

4.config.cfg

#this is a comment
a = 100
b = 100 #this comment is valid

# this is another
c = 200

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值