代码改变世界

一个参数处理类

2015-03-30 23:37  rangers  阅读(340)  评论(0编辑  收藏  举报

在最近的项目中,使用的插件式架构, 插件的每个功能都需要用户输入的参数(所需的参数值配置在xml文件中),之前的做法是将每个功能需要的所有参数定义成结构体
程序一开始,解析XML文件,将对应名称的参数值填充到相应的字段中。如果参数个数很多,则参数结构体的字段就会很多,写起来就会很麻烦,而且当
某个模块新增参数时(在xml文件中添加),就必须修改参数结构体,不利于程序扩展。
所以写了一个下面的参数类,将xml中所有参数按 参数名(string) 参数值(string)键值对的形式存储到map中,当需要某个参数时,按参数名称
提取即可(且不区分参数名的大小写),使用者自己控制将参数解析成什么形式(整型,浮点型等) ,而且新增某个参数时,只需在xml按照一定的规则添加即可(参数名 参数值),不需要修改参数类。用的时候直接按名称提取即可。

记录如下:

参数配置XML文件格式简化为:

<Params>
<Item Name="NetWorkType" Value="UMTS"></Item>
<Item Name="GridCntThreshold" Value="100"></Item>
</Params>

参数类如下:

param.h

#ifndef PARAM_H_
#define PARAM_H_
#include <map>
#include <string>
#include <algorithm>
#include <sstream>

using std::map;
using std::string;
using std::stringstream;

//参数类
class CParam
{
public:
	struct NoCaseCompare
	{
		bool operator()(const string & str1, const string & str2)
		{
			string upper_str1(str1);
			string upper_str2(str2);
			std::transform(upper_str1.begin(),upper_str1.end(),upper_str1.begin(),toupper);
			std::transform(upper_str2.begin(),upper_str2.end(),upper_str2.begin(),toupper);
			return upper_str1.compare(upper_str2) >= 0 ? false : true;
		}
	};

	typedef map<string,string,NoCaseCompare> StrMap;

	CParam();
	virtual ~CParam();
	//设置参数值
	template <typename T>
	void SetParam(const string & param_name, const T & param_val);
	
	//得到double型参数
	double GetParamDouble(const string & param_name);
	//得到整型参数值
	int GetParamInt(const string & param_name);
	//得到字符串参数值
	string GetParamString(const string & param_name);
	//得到bool型参数值
	bool GetParamBool(const string & param_name);
	
	//加载参数配置文件,将所有参数按 参数名(string)-> 值(string) 的形式存储
	bool LoadParamXml(const string & param_file_path);
	//清除所有参数
	void Clear();

private:
	const char* FindParam(const string & param_name);

private:
	StrMap _params;
};

template <typename T>
void CParam::SetParam(const string & param_name, const T & param_val)
{
	stringstream ss;
	ss << param_val;	
	_params[param_name] = ss.str();

}
#endif

param.cpp

#define TIXML_USE_STL
#include "param.h"
#include <tinyxml.h>

CParam::CParam()
{

}

CParam::~CParam()
{

}

double CParam::GetParamDouble( const string & param_name )
{
	double val = 0;
	const char * pStr = this->FindParam(param_name);
	if (NULL != pStr)
	{
		val = atof(pStr);
	}
	return val;
}

const char * CParam::FindParam(const string & param_name)
{
	StrMap::const_iterator it = _params.find(param_name);
	if (it != _params.end())
	{
		return it->second.c_str();
	}
	return NULL;

}

int CParam::GetParamInt( const string & param_name )
{
	int val = 0;
	const char * pStr = FindParam(param_name);
	if (NULL != pStr)
	{
		val = atoi(pStr);
	}
	return val;
}

string CParam::GetParamString( const string & param_name )
{
	StrMap::const_iterator it = _params.find(param_name);
	if (it != _params.end())
	{
		return it->second;
	}
	return "";
}

bool CParam::GetParamBool( const string & param_name )
{
	bool val = false;
	const char * pStr = FindParam(param_name);
	if (NULL != pStr)
	{
		string str(pStr);
		std::transform(str.begin(),str.end(),str.begin(),tolower);
		if (str == "t" || str == "true" || atoi(str.c_str()) > 0)
		{
			val = true;
		}
	}
	return val;
}

bool CParam::LoadParamXml( const string & param_file_path )
{
	//从参数 配置文件中读取所有参数
	TiXmlDocument doc;
	if (!doc.LoadFile(param_file_path))
	{
		return false;
	}
	TiXmlHandle handle(&doc);
	TiXmlElement *pChild = handle.FirstChild("Params").FirstChild("Item").Element();
	for (; NULL != pChild; pChild = pChild->NextSiblingElement())
	{
		string name;
		string val;
		pChild->QueryStringAttribute("Name",&name);
		pChild->QueryStringAttribute("Value",&val);
		this->SetParam(name,val);
	}
	return true;
}

void CParam::Clear()
{
	_params.clear();
}

测试代码如下:

CParam param;
param.LoadParamXml("d:\\TEST\\Param.xml");
cout << param.GetParamDouble("GridCntThreshold") << endl;
cout << param.GetParamString("NETWORKTYPE") << endl;