• 封装游戏配表读取和存储(xml格式);支持行列存取,标题存取


    做服务器肯定会涉及到游戏配表,而读取游戏配表是一个必备技能;

    之前一直都是采用TinyXml直接读,匹配字符串,每次加个表都是一大坨代码,看着也是心累;

    因此利用了闲暇的时间封装了一个 xml配置表 读取类;

    1.支持 按照 列*行的读取方法

    2.支持 按照 "标题"*行的读取方法

    3.支持 按照 列*行的修改

    4.支持 按照 "标题"*行的修改

    //例子用的xml , 库用的是 tinyxml 2.5.3

    <?xml version="1.0" encoding="gbk" standalone="yes" ?>
    <config>
        <Quest Quest_ID="1" Quest_Star="1" Quest_Limit="0" Quest_Type="6" Quest_TarID="0" Quest_Tar_Num="100" Award_Type="2" Award_ID="1" Awa_Num="5000" Quest_Des="击杀%d" bModify="0" bNew="0" />
        <Quest Quest_ID="2" Quest_Star="1" Quest_Limit="0" Quest_Type="6" Quest_TarID="0" Quest_Tar_Num="500" Award_Type="2" Award_ID="1" Awa_Num="10000" Quest_Des="击杀%d" bModify="0" bNew="0" />
        <Quest Quest_ID="3" Quest_Star="1" Quest_Limit="0" Quest_Type="10" Quest_TarID="0" Quest_Tar_Num="3" Award_Type="2" Award_ID="1" Awa_Num="6000" Quest_Des="击杀%d" bModify="0" bNew="0" />
        <Quest Quest_ID="4" Quest_Star="1" Quest_Limit="0" Quest_Type="10" Quest_TarID="0" Quest_Tar_Num="5" Award_Type="2" Award_ID="1" Awa_Num="8000" Quest_Des="击杀%d" bModify="0" bNew="0" />
        <Quest Quest_ID="5" Quest_Star="1" Quest_Limit="0" Quest_Type="11" Quest_TarID="0" Quest_Tar_Num="1" Award_Type="2" Award_ID="1" Awa_Num="10000" Quest_Des="击杀%dBOSS" bModify="0" bNew="0" />
        <Quest Quest_ID="6" Quest_Star="1" Quest_Limit="0" Quest_Type="11" Quest_TarID="0" Quest_Tar_Num="2" Award_Type="2" Award_ID="1" Awa_Num="15000" Quest_Des="击杀%dBOSS" bModify="0" bNew="0" />
        <Quest Quest_ID="7" Quest_Star="1" Quest_Limit="0" Quest_Type="6" Quest_TarID="0" Quest_Tar_Num="100" Award_Type="2" Award_ID="2" Awa_Num="10" Quest_Des="击杀%d" bModify="0" bNew="0" />
        <Quest Quest_ID="8" Quest_Star="1" Quest_Limit="0" Quest_Type="6" Quest_TarID="0" Quest_Tar_Num="500" Award_Type="2" Award_ID="2" Awa_Num="25" Quest_Des="击杀%d" bModify="0" bNew="0" />
        <Quest Quest_ID="9" Quest_Star="1" Quest_Limit="0" Quest_Type="10" Quest_TarID="0" Quest_Tar_Num="3" Award_Type="2" Award_ID="2" Awa_Num="15" Quest_Des="击杀%d赏金" bModify="0" bNew="0" />
        <Quest Quest_ID="10" Quest_Star="1" Quest_Limit="0" Quest_Type="10" Quest_TarID="0" Quest_Tar_Num="5" Award_Type="2" Award_ID="2" Awa_Num="20" Quest_Des="击杀%d赏金" bModify="0" bNew="0" />
        <Quest Quest_ID="11" Quest_Star="1" Quest_Limit="0" Quest_Type="11" Quest_TarID="0" Quest_Tar_Num="1" Award_Type="2" Award_ID="2" Awa_Num="25" Quest_Des="击杀%d" bModify="0" bNew="0" />
        <Quest Quest_ID="12" Quest_Star="1" Quest_Limit="0" Quest_Type="11" Quest_TarID="0" Quest_Tar_Num="2" Award_Type="2" Award_ID="2" Awa_Num="40" Quest_Des="击杀%d" bModify="0" bNew="0" />
    </config>
    

     下面就直接上代码;

    #pragma once
    #pragma warning(disable:4786)
    #pragma warning(disable:4503)
    
    #include "tinyxml.h"
    #include <map>
    #include <string>
    
    using namespace std;
    class CRowStr{
    public:
    	CRowStr(int row,string title)
    	{
    		_row=row;
    		_title=title;
    	}
    
    	bool operator<( const  CRowStr& a) const
    	{
    		if(this->_row<a._row)
    			return true;
    		else
    		return false;
    	};
    	
    	int _row;//行
    	string _title;//标题
    };
    
    typedef map<CRowStr, string> mpCfgRow;
    typedef map<int, mpCfgRow*> mpCfgList;
    
    //默认从第1列开始读取
    #define ROWBEGIN 1
    
    //默认从第1行开始读取
    #define LINEBEGIN 1
    
    //非元素模式从1000开始
    #define NEXTBEGIN 1000
    
    //暂时不支持非元素模式
    class CXmlFileReader
    {
    public:
    	CXmlFileReader(const char* _filename,const int _flag=1);
    	~CXmlFileReader();
    
    	//获取第line行的_title字段的数据
    	char* GetValueByTitle(const char*_title/*字段*/, const int _line=LINEBEGIN/*行数*/);
    	//获取第line行的_row列数据
    	char* GetValueByRow(const int _row=ROWBEGIN/*列数*/, const int _line=LINEBEGIN/*行数*/);
    	
    	//设置第line行的_title字段的数据
    	bool SetValueByTitle(const char *_value/*内容*/,const char*_title/*字段*/,const int _line=LINEBEGIN/*行数*/);
    	//设置第line行的_row列数据
    	bool SetValueByRow(const char *_value/*内容*/,const int _row=ROWBEGIN/*列数*/,const int _line=LINEBEGIN/*行数*/);
    	
    	int GetLines();//获取行数
    	int GetRows();//获取列数
    	
    private:
    	void _loadFile();
    	void _clearMap();
    	void _example();//例子
    	
    private:
    	bool					m_load_ok;
    	string 					m_path;
    	int						m_Flag;
    	int						m_Maxlines;
    	int						m_Maxrows;
    	mpCfgList*				m_config_map;
    };
    

     下面是.cpp文件

    #include "XmlControl.h"
    
    CXmlFileReader::CXmlFileReader(const char* _filename,const int _flag)
    {
        m_Maxlines=0;
        m_Maxrows=0;
        m_config_map = new mpCfgList;
        m_path = string(_filename);
        m_Flag = _flag;
        _loadFile();
    }
    
    CXmlFileReader::~CXmlFileReader()
    {
        _clearMap();
    }
    
    void CXmlFileReader::_example()
    {
        //用法
        string filePath = "D:\Quest.xml";
        CXmlFileReader Reader(filePath.c_str());
    
        //读取
    	string _desRowOld(Reader.GetValueByRow(10,2));
    	string _desTitleOld(Reader.GetValueByTitle("Quest_Des",3));
        //设置节点值
    	Reader.SetValueByTitle("Testtitle","Quest_Des",3);
    	Reader.SetValueByRow("Testrow",10,2);
        //读取
    	string _desRowNew(Reader.GetValueByRow(10,2));
    	string _desTitleNew(Reader.GetValueByTitle("Quest_Des",3));
    }
    
    int CXmlFileReader::GetLines()
    {
        if(!m_load_ok)
            return 0;
        return m_Maxlines;
    }
    
    int CXmlFileReader::GetRows()
    {
        if(!m_load_ok)
            return 0;
        return m_Maxrows;
    }
    
    char* CXmlFileReader::GetValueByTitle(const char* title,const int line)
    {
        if (!m_load_ok)
            return NULL;
        char* value = NULL;
        mpCfgList::iterator itLine = m_config_map->find(line);
        if(itLine == m_config_map->end())
            return NULL;
        mpCfgRow* mpRowValue = itLine->second;
        mpCfgRow::iterator itValue = mpRowValue->begin();
        for (; itValue != mpRowValue->end(); itValue++){
            const CRowStr key=itValue->first;
            if (key._title==string(title)){
                value = (char*) itValue->second.c_str();
                break;
            }
        }
        return value;
    }
    
    char* CXmlFileReader::GetValueByRow(const int row, const int line)
    {
        if (!m_load_ok)
            return NULL;
        char* value = NULL;
        mpCfgList::iterator itLine = m_config_map->find(line);
        if(itLine == m_config_map->end())
            return NULL;
        mpCfgRow* mpRowValue = itLine->second;
        mpCfgRow::iterator itValue = mpRowValue->begin();
        for (; itValue != mpRowValue->end(); itValue++){
            const CRowStr key = itValue->first;
            if(key._row == row){
                value = (char*) itValue->second.c_str();
                break;
            }
        }
        return value;
    }
    
    bool CXmlFileReader::SetValueByTitle(const char * value,const char* title,const int line)
    {
        TiXmlDocument _doc;
        int _curline=line;
        int _flag = m_Flag;
    	if(!_doc.LoadFile(m_path.c_str())||!title||!value)
            return false;
    	//改xml值
        TiXmlElement* _pelement = _doc.RootElement(); //root
    	while(_flag--){
    		_pelement = _pelement->FirstChildElement(); //指向下一个
    	}
    	while(_pelement){
    		TiXmlAttribute* _attributeOfStudent = _pelement->FirstAttribute(); //获得每一级的各种属性
    		if(--_curline>0){
                _pelement = _pelement->NextSiblingElement();
                continue;
    		}
    		while(_attributeOfStudent){
                if(string(_attributeOfStudent->Name())==title){
    				_attributeOfStudent->SetValue(value);
                    break;
    			}
    			_attributeOfStudent = _attributeOfStudent->Next();//指向下一个元素
    		}
            break;
    	}
        //保存
        if(!_doc.SaveFile(m_path.c_str()))
            return false;
        
        //改内存里的值
        mpCfgList::iterator itLine = m_config_map->find(line);
        if(itLine == m_config_map->end())
            return NULL;
        mpCfgRow* mpRowValue = itLine->second;
        mpCfgRow::iterator itValue = mpRowValue->begin();
        for (; itValue != mpRowValue->end(); itValue++){
            const CRowStr key = itValue->first;
    		string _strtile = string(title);
            if (key._title==_strtile){
                string _newValue = string(value);
                itValue->second = _newValue;
                break;
            }
        }
    	return true;
    }
    
    bool CXmlFileReader::SetValueByRow(const char * value,const int row,const int line)
    {
        TiXmlDocument _doc;
        int _curline=line;
        int _currow=row;
        int _flag = m_Flag;
    	if(!_doc.LoadFile(m_path.c_str())||!value)
            return false;
    	//改xml值
        TiXmlElement* _pelement = _doc.RootElement();
    	while(_flag--){
    		_pelement = _pelement->FirstChildElement();
    	}
    	while(_pelement){
    		TiXmlAttribute* _attributeOfStudent = _pelement->FirstAttribute();
    		if(--_curline>0){
                _pelement = _pelement->NextSiblingElement();
                continue;
    		}
    		while(_attributeOfStudent){
                if(--_currow>0){
                    _attributeOfStudent = _attributeOfStudent->Next();
                    continue;
        		}
    			_attributeOfStudent->SetValue(value);
                break;
    		}
            break;
    	}
        //保存
        if(!_doc.SaveFile(m_path.c_str()))
            return false;
        
        //改内存里的值
        mpCfgList::iterator itLine = m_config_map->find(line);
        if(itLine == m_config_map->end())
            return NULL;
        mpCfgRow* mpRowValue = itLine->second;
        mpCfgRow::iterator itValue = mpRowValue->begin();
        for (; itValue != mpRowValue->end(); itValue++){
            const CRowStr key = itValue->first;
            if(key._row==row){
                string _newValue = string(value);
                itValue->second = _newValue;
                break;
            }
        }
    	return true;
    }
    
    void CXmlFileReader::_clearMap()
    {
        if(!m_config_map)
            return;
        mpCfgList::iterator it = m_config_map->begin();
        for (; it != m_config_map->end(); it++){
    		delete it->second;
        }
        
        delete m_config_map;
    	m_config_map = NULL;
    }
    
    void CXmlFileReader::_loadFile()
    {
        int _flag = m_Flag;
    	TiXmlDocument _doc;
        int _line=LINEBEGIN;
    	//int _nxline=NEXTBEGIN;
        int _row=ROWBEGIN;
    	if(!_doc.LoadFile(m_path.c_str())){
            m_load_ok=false;
            return;
        }
        TiXmlElement* _pelement=_doc.RootElement(); //root
    	while(_flag--){
    		_pelement=_pelement->FirstChildElement();//指向下一个大节点
    	}
        switch (_pelement->Type())  
        {  
            case TiXmlText::DOCUMENT:break;  
            case TiXmlText::DECLARATION:break;  
            case TiXmlText::TEXT:break;  
            case TiXmlText::UNKNOWN:break;  		
            case TiXmlText::COMMENT:break;  
            case TiXmlText::ELEMENT:
    		{
    			while(_pelement){
    				TiXmlAttribute* _attributeOfStudent=_pelement->FirstAttribute(); //获得每一级的各种属性
    				if (_attributeOfStudent)
    				{
    					mpCfgRow* mpRowValue= new mpCfgRow();
                        int _rowdex=ROWBEGIN;
    					while (_attributeOfStudent){
                            CRowStr _rowinfo(_rowdex++,string(_attributeOfStudent->Name()));
    						mpRowValue->insert(make_pair(_rowinfo,string(_attributeOfStudent->Value())));//存储第_line行的所有列
    						_attributeOfStudent=_attributeOfStudent->Next();//指向下一个元素
    						++_row;
    					}
    					_pelement=_pelement->NextSiblingElement();
    					m_config_map->insert(make_pair(_line++,mpRowValue));//存储_line行的所有元素
    				}
    				else
    				{
    					/*mpCfgRow* mpRowValue= new mpCfgRow();
    					mpRowValue->insert(make_pair(string(_pelement->Value()),
    						string(_pelement->FirstChild()->Value())));//存储第_line行的所有列
    					_pelement=_pelement->NextSiblingElement();
    					m_config_map->insert(make_pair(_nxline++,mpRowValue));//存储_line行的所有元素
    					*/
    				}
    				
    			}
    			m_Maxlines=_line-LINEBEGIN;
    			m_Maxrows=(_row-ROWBEGIN)/m_Maxlines;
    			m_load_ok=true;
    		}
            break;
        }
    }
    
  • 相关阅读:
    使用jmeter进行api接口压力测试
    MAC OS环境下搭建基于Python语言的appium自动化测试环境
    jmeter+python可以用jython来实现
    navicat12.0.27 Mac版破解方法
    uiautomatorviewer连接机器点击报错Unexpected error while obtaining UI hierarchy
    appium+python,终端键值表
    自动化测试--Appium简单的测试demo
    appium+python搭建自动化测试框架_TestAPP框架(三)
    深入理解Java虚拟机-----第二章
    ViewModel组件
  • 原文地址:https://www.cnblogs.com/left69/p/5753630.html
Copyright © 2020-2023  润新知