您的位置:首页 > 编程语言 > C语言/C++

(转载)C++中枚举与字符串相互转换

2010-12-05 15:15 246 查看

C++中枚举与字符串相互转换

前言

有的时候我们喜欢使用一些外部的文件保存管理一些配置信息,这些配置文件大多都是文本格式例如ini,xml等,这样方便编辑和管理。因此在使用的过程中必然会遇到各种字符串转换问题。

最常见的便是将字符串的数字转换为对应的整形(integer)或者浮点(float),如果遇到枚举类型,可能便会想当做是整形来处理,但觉得不是特别理想。如果能有办法直接转换为枚举会方便很多。

案例

一个简单的配置文件:

1


[config]


2


fooInt = 10


3


fooFloat = 2.5


4


fooEnum =cpp


在C++里面有枚举:

1


enum


ProgLang


2


{


3




e_cpp,


4




e_java,


5




e_csharp


6


};


如果对于前面两个数值,可以很简单的读取,例如:

1


Config cfg;//Config 类见<<C++编写Config类读取配置文件>>


2


cfg.Load(


"config.ini"


);


3


4


int


fooInt = cfg.GetValue<


int


>(


"fooInt"


);


5


float


fooFloat = cfg.GetValue<


float


>(


"fooFloat"


);


对于后面那个枚举,可能就稍微麻烦一点:

1


ProgLang fooEnum;


2


const


char


* rawData = cfg.GetValue<


const


char


*>(


"fooEnum"


);


3


if


(


strcmp


(rawData,


"cpp"


)) fooEnum =e_cpp;


4


else


if


(


strcmp


(rawData,


"java"


)) fooEnum =e_java;


5


else


if


(


strcmp


(rawData,


"csharp"


)) fooEnum =e_csharp;


如果直接在配置文件里面不保存”cpp“字符串而直接保存枚举值,这里便可以当整形取出来再做类型转换。不过这样不安全,也不好维护,如果枚举内部的定义发生了变化,外部保存的数据自然也就会失效出错。

解决方案

C++没有(也不可能会有)反射机制,枚举成员在编译以后也已经变成了纯粹的数值,失去了名字。所以想使用字符串作为搜索依据,必须为枚举保留一份名字信息,例如:

1


enum


ProgLang


2


{


3




e_cpp,


4




e_java,


5




e_csharp


6


};


7


const


char


* ProgLangNames[] = {


"cpp"


,


"java"


,


"csharp"


};


这个字符串数组只能预先写好,无论是手动还是通过工具自动生成。然后可以在这个字符串数组里面搜索目标字符串,将找到的结果下标转换为对应的枚举值即可,例如:

1


for


(


int


i = 0; i <


sizeof


(ProgLangNames) /


sizeof


(ProgLangNames[0]); ++i)


2


{


3




if


(


strcmp


(rawData,ProgLangNames[i]))


4




{


5




fooEnum =


static_cast


<ProgLang>(i);


6




break


;


7




}


8


}


枚举关联字符串

解决方案找到了,随之而来的问题就是如何将枚举与所需要的字符串查找表联系起来。如有多个枚举:

01


enum


ProgLang


02


{


03




e_cpp,


04




e_java,


05




e_csharp


06


};


07


const


char


* ProgLangNames[] = {


"cpp"


,


"java"


,


"csharp"


};


08


09


enum


ScriptLang


10


{


11




e_lua,


12




e_actionscript,


13




e_javascript


14


};


15


const


char


* ScriptLangNames[] = {


"lua"


,


"actionscript"


,


"javascript"


};


枚举不像类或结构体可以定义自己的成员变量,所以查找表只能在外部定义,通过实例化模板类来将他们相互联系起来。例如:

1


<


template


EnumType>


2


struct


SEnumName


3


{


4




static


const


char


* List[];


5


}


这定义了一个查找表的模板结构体,然后将之前的代码改造为:

01


enum


ProgLang


02


{


03




e_cpp,


04




e_java,


05




e_csharp


06


};


07


const


char


* SEnumName<ProgLang>::List[] =


08


{


09




"cpp"


,


10




"java"


,


11




"csharp"


12


};


13


14


enum


ScriptLang


15


{


16




e_lua,


17




e_actionscript,


18




e_javascript


19


};


20


const


char


* SEnumName<ScriptLang>::List[] =


21


{


22




"lua"


,


23




"actionscript"


,


24




"javascript"


25


};


然后便可以实现字符串转枚举的功能:

view source

print

?

01


template


<


typename


EnumType>


02


EnumType ConvertStringToEnum(


const


char


* pStr)


03


{


04




EnumType fooEnum =


static_cast


<EnumType>(-1);


05




int


count =


sizeof


(SEnumName<EnumType>::List) /


06




sizeof


(SEnumName<EnumType>::List[0]);


07




for


(


int


i = 0; i <count; ++i)


08




{


09




if


(


strcmp


(rawData,SEnumName<EnumType>::List[i]))


10




{


11




fooEnum =


static_cast


<ProgLang>(i);


12




break


;


13




}


14




}


15




return


fooEnum;


16


}


这样一来,最开始的问题就可以简化为:

1


ProgLang fooEnum =cfg.GetValue<ProgLang>(


"fooEnum"


);


有了这种方式,自然枚举反转回字符串也很容易了,就不再赘述了。



转载出处: http://a.vifix.us/blog/cpp-convert-string-enum
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: