打造 C++ 最灵活动态数组结构 (二)
2008-07-01 11:42
232 查看
第二版代码如下:
1 MyData.h
/*--------------------------------*/ C++ 散列化数组结构 cjxxstar@gmail.com cjxx 2008-06-27 /*--------------------------------*/ #ifndef __CJ_MY_DATA_H__ #define __CJ_MY_DATA_H__ #include <iostream> #include <string> #include <map> using namespace std; // 数字索引字符前缀 #define INT_INDEX_PRO_STR "INT_INDEX_" // 相关头信息 class MyData; // 序列化时的风格类型 enum PRINT_R_STYLE { PHP,JS }; // 序列化一个字串到MyData MyData& Serialize(const char* serStr, MyData* dVal = NULL); // 反序列化一个MyData到 字符串 bool UnSerialize(MyData* dVal, string& unserStr); // 格式化输出一个MyData 结构 -- 调试用 void print_r(MyData& data); // 构造MyData 格式化字串 string& print_s(MyData& data, string& str, bool bFormat = false, enum PRINT_R_STYLE style = PHP, int level = 0) ; // 递归遍历 MyData 并执行用户自定义函数 void ForEachData(MyData& data, void* pCallBackFunc); class MyData { public: enum ENUM_DATA_TYPE { DATA_TYPE_DEF = 0, // 初始类型 DATA_TYPE_DAT = 1, // 数组类型 DATA_TYPE_INT = 2, // 整数类型 DATA_TYPE_STR = 3, // 字符类型 }; typedef map<string, MyData> MAP_MY_DATA; public: // 构造 MyData() { this->Init(); } // 序列化构造 MyData(const char* dVal) { this->Init(); Serialize(dVal, this); } // 析构 ~MyData() { this->Clear(); } // 判断类型 bool IsType(enum ENUM_DATA_TYPE eType) { return m_cType == eType; } // 获取类型 enum ENUM_DATA_TYPE Type() { return m_cType; } // 获取MAP MAP_MY_DATA& Map() { return m_mapMyData; } // 获取整形数据 int i() { return (m_cType == DATA_TYPE_INT) ? m_intData : 0; } // 获取字符数据 const char* c() { return (m_cType == DATA_TYPE_STR) ? m_strData.c_str() : ""; } // 获取反序列化字串 const char* u() { m_strUnSer = ""; return UnSerialize(this, m_strUnSer) ? m_strUnSer.c_str() : ""; } // 赋值为整数 void operator=(int iVal) { this->Clear(); m_intData = iVal; m_cType = DATA_TYPE_INT; this->SetFatherDat(); } // 赋值为字符 void operator=(const char* cVal) { this->Clear(); m_strData = cVal; m_cType = DATA_TYPE_STR; this->SetFatherDat(); } // 赋值为数据 void operator=(const MyData& dVal) { this->Clear(); m_strData = dVal.m_strData; m_strUnSer = dVal.m_strUnSer; m_intData = dVal.m_intData; m_iNowIndex = dVal.m_iNowIndex; m_mapMyData = dVal.m_mapMyData; m_cType = dVal.m_cType; this->SetFatherDat(); } // 自动增加一个数字索引 MyData& operator()() { m_iTmpIndex = m_iNowIndex; return this->Get(StrIndex(m_iNowIndex++)); } // 整形索引 MyData& operator[](int keyName) { m_iTmpIndex = keyName; return this->Get(StrIndex(keyName)); } // 字符型索引 MyData& operator[](const char* keyName) { m_iTmpIndex = 0; return this->Get(keyName); } // 自动转换成 int operator int() { return m_intData; } // 自动转换成 const char* operator const char*() { return m_strData.c_str(); } private: void Clear() { if (m_cType == DATA_TYPE_DAT) { m_mapMyData.clear(); } } void Init() { m_iNowIndex = 0; m_iTmpIndex = 0; m_intData = 0; m_pFather = NULL; m_cType = DATA_TYPE_DEF; m_mapMyData.clear(); } const char* StrIndex(unsigned int index) { char buf[64] = {0}; sprintf_s(buf, INT_INDEX_PRO_STR"%d", index); m_strUnSer = buf; return m_strUnSer.c_str(); } MyData& Get(const char* keyName) { MAP_MY_DATA::iterator iter; if (NULL == keyName) { iter = m_mapMyData.find(""); } else { iter = m_mapMyData.find(keyName); } if (iter != m_mapMyData.end()) { return (*iter).second; } else { pair<MAP_MY_DATA::iterator, bool> Insert_Pair; MyData data; if (NULL == keyName) { Insert_Pair = m_mapMyData.insert(MAP_MY_DATA::value_type("", data)); } else { Insert_Pair = m_mapMyData.insert(MAP_MY_DATA::value_type(keyName, data)); } (*Insert_Pair.first).second.SetFather(this); return (*Insert_Pair.first).second; } } void SetFatherDat() { if (NULL != this->GetFather()) { if (! this->GetFather()->IsType(DATA_TYPE_DAT)) { this->GetFather()->m_cType = DATA_TYPE_DAT; } if (this->GetFather()->m_iNowIndex < this->GetFather()->m_iTmpIndex) { this->GetFather()->m_iNowIndex = this->GetFather()->m_iTmpIndex + 1; } this->GetFather()->SetFatherDat(); } } void SetFather(MyData* pData) { m_pFather = pData; } MyData* GetFather() { return m_pFather; } private: enum ENUM_DATA_TYPE m_cType; string m_strData; string m_strUnSer; int m_intData; int m_iNowIndex; int m_iTmpIndex; MyData* m_pFather; MAP_MY_DATA m_mapMyData; }; #endif // end define __CJ_MY_DATA_H__
2 MyData.cpp
#include "MyData.h" // 序列化成数据 MyData& Serialize(const char* serStr, MyData* dVal /*= NULL*/) { MyData* pDVal; if (dVal == NULL) { pDVal = new MyData; } else { pDVal = dVal; } // 序列化并添加数据 return (*pDVal); } // 反序列化为字串 bool UnSerialize(MyData* dVal, string& unserStr) { if (NULL == dVal) { return false; } string str = ""; if (dVal->IsType(MyData::DATA_TYPE_DAT)) { str += "{"; } print_s(*dVal, str, false, JS, 0); if (dVal->IsType(MyData::DATA_TYPE_DAT)) { str += "}"; } unserStr = str; return true; } string& print_s(MyData& data, string& str, bool bFormat /*= false*/, enum PRINT_R_STYLE style /*= PHP*/, int level /*= 0*/) { char p_style[5][15] = {" =>array (", ")", "=>", "/"", ","}; char j_style[5][15] = {": {" , "}", ":" , "/"", ","}; char (* u_style)[15] = style == PHP ? p_style : j_style; string space = ""; if (bFormat) { for (int i = 0; i < level; i++) { space += " "; } ++level; } if (data.IsType(MyData::DATA_TYPE_DAT)) { MyData::MAP_MY_DATA::iterator iter = data.Map().begin(); for (;iter != data.Map().end();) { string keyString = ""; if ((*iter).first.substr(0,strlen(INT_INDEX_PRO_STR)) == INT_INDEX_PRO_STR) { keyString = (*iter).first.substr(strlen(INT_INDEX_PRO_STR), (*iter).first.length()); } else { keyString+= u_style[3]; keyString+= (*iter).first.c_str(); keyString+= u_style[3]; } if ((*iter).second.IsType(MyData::DATA_TYPE_DAT)) { if (bFormat) { str += space; } str += keyString; str += u_style[0]; if (bFormat) { str += "/n"; } str = print_s((*iter).second, str, bFormat, style, level); if (bFormat) { str += space; } str += u_style[1]; } else if ((*iter).second.IsType(MyData::DATA_TYPE_INT)) { char buf[12] = {0}; sprintf_s(buf, "%d", (*iter).second.i()); if (bFormat) { str += space; } str += keyString; str += u_style[2]; str += buf; } else if ((*iter).second.IsType(MyData::DATA_TYPE_STR)) { if (bFormat) { str += space; } str += keyString; str += u_style[2]; str += (*iter).second.c(); } if (++iter != data.Map().end()) { str += u_style[4]; } if (bFormat) { str += "/n"; } } } else if (data.IsType(MyData::DATA_TYPE_INT)) { char buf[12] = {0}; sprintf_s(buf, "%d", data.i()); if (bFormat) { str += space; } str += buf; if (bFormat) { str += "/n"; } } else if (data.IsType(MyData::DATA_TYPE_STR)) { if (bFormat) { str += space; } str += data.c(); if (bFormat) { str += "/n"; } } return str; } void print_r(MyData& data) { string str = "/n{/n"; print_s(data, str, true, JS, 1); str += "}"; printf("%s", str.c_str()); } void ForEachData(MyData& data, void* pCallBackFunc) { }
3 testMain.cpp
#include "MyData.h" int main(void) { int i = 0; MyData testData; MyData testData2("[1:22, '2':0, 'dff': [1:3]]"); testData[0] = 100; testData[1] = "abc"; testData[3] = 3; testData[1] = 1; testData[6] = 2; testData()[1] = 41; testData[5]()[6] = 506; testData[5]["a"][1] = 501; testData[5][3][1] = 511; testData[5]()[2] = 541; testData["a"]() = Serialize("[1:22, '2':0, 'dff': [1:3]]"); testData["a"] = "fuck"; testData["a"][2] = "a"; testData["a"]() = "b"; testData["a"]() = "c"; testData2[1] = "abc"; testData2[2] = 3; testData2[3]() = 4; testData["c"]() = 1; testData["c"]() = testData2; testData[2][i][i] = 2; int b = testData[0]; const char* p = testData[1]; printf("%d/n", b); printf("%s/n", p); print_r(testData); printf("%s", testData.u()); getchar(); return 1; }
功能: 1 增加了类型自动识别转换的操作,这个功能需要依赖C++的编译器而不是用户逻辑,使用时小心。 2 增加反序列化功能,此功能可以将自身导出成字串用来存储发送,目前两种可选方案 -- JSON -- PHP方式
相关文章推荐
- 打造 C++ 最灵活动态数组结构 (一)
- 打造 C++ 最灵活动态数组结构 (三)
- c++ primer plus 习题5.7(使用new为结构创建动态数组)
- 【C++】动态结构数组简单运用
- C++中灵活数组结构使用
- c++动态结构数组、文件输入输出、分支语句和循环语句
- 你好,C++(23) 4.4.2 工资程序成长记:用数组处理批量数据,用循环结构执行重复动作
- 创建结构candybar,要求用new来动态分配结构数组
- C++:多维数组的动态分配(new)和释放(delete)
- C++学习笔记——C++动态数组的创建与删除
- 【C++学习】通过输入数来确定一个数组的动态大小
- C++实现仿vector的动态数组
- C++中一维,二维动态数组的建立,与内存的释放delete 和 delete[] 的使用
- C++:多维数组的动态分配(new)和释放(delete)
- C++动态数组简单模拟二叉堆
- c/c++ 多维数组的动态分配
- C++学习总结——顺序存储,链式存储,索引存储,哈希存储的优缺点,以及vector数组,list链表,十字链表,索引结构,hash表的实现
- C++ 数组直接存入已有的动态Eigen 矩阵 (Mapping array back to an existing Eigen matrix)
- 数据结构之动态数组
- c++ 依据输入动态声明数组(一维,二维)