C++ 我如何';ToString()';C+中的枚举+;?
在Java和C语言中,我只需要调用ToStringC++ 我如何';ToString()';C+中的枚举+;?,c++,C++,在Java和C语言中,我只需要调用ToString enum Colours { Red =0, Green=1, Blue=2 }; 我需要创建一个字符串,如:“无效颜色”“选定颜色+”。这本质上是不可能的 一个C++的枚举只是一组编译时间名称的数字。 在运行时,它们与普通数字无法区分 您需要编写一个返回字符串的switch语句。您可以将名称存储在字符串数组中,由enum值索引 enum Colours { Red =0, Green=1, B
enum Colours
{
Red =0,
Green=1,
Blue=2
};
我需要创建一个字符串,如:“无效颜色”“选定颜色+”。这本质上是不可能的
一个C++的枚举只是一组编译时间名称的数字。 在运行时,它们与普通数字无法区分
您需要编写一个返回字符串的
switch
语句。您可以将名称存储在字符串数组中,由enum
值索引
enum Colours
{
Red =0,
Green=1,
Blue=2
};
char* names[3] = {"Red", "Green", "Blue"};
然后您可以打印:“无效颜色”+“已选择名称[颜色]+”。
但是,如果不按顺序定义
enum
值,这种方法可能不会非常有用。在这种情况下,这种方法将浪费内存。正如Alexander Gessler所提到的,用开关
在枚举
值上编写函数会很有用。另一种选择可能是STL中的映射。您必须手动执行,即
const char* ToString(Colours co) {
switch(co) {
case Red:
return "Red";
// ...
}
}
也可以使用查找表。我还见过人们使用自定义脚本在源代码之上生成这样的东西
enum Color
{
Red =0,
Green=1,
Blue=2
};
std::string ColorMap[] = { "Red", "Green","Blue" };
使用ColorMap[c]
获取字符串表示形式:
std::string msg = "Invalid colour '" + ColorMap[c] + "' selected.";
但是,如果enum的值不是连续的,则可以使用std::map
作为:
enum Color
{
Red = 0x1,
Green = 0x2,
Blue = 0x4,
Black = 0x8,
};
//C++11 only, as it uses std::initializer_list
std::map<Color, std::string> ColorMap = {
{Red, "Red"},
{Green, "Green"},
{Blue, "Blue"},
{Black, "Black"}
};
//same as before!
std::string msg = "Invalid colour '" + ColorMap[c] + "' selected.";
枚举颜色
{
红色=0x1,
绿色=0x2,
蓝色=0x4,
黑色=0x8,
};
//仅限C++11,因为它使用std::initializer\u list
std::map ColorMap={
{红色,“红色”},
{绿色,绿色},
{蓝色,蓝色},
{黑色,“黑色”}
};
//和以前一样!
std::string msg=“无效颜色””+ColorMap[c]+“”已选定。“;
正如@FlopCoder所说:
enum Colours
{
Red =0,
Green=1,
Blue=2
};
char* ColourNames[] = { "Red", "Green", "Blue" };
int colour = Green;
printf( "Invalid colour '%s' selected.", ColourNames[ colour ] );
当然,只有当枚举从0开始并且是连续的时,这才有效。
虽然纳瓦兹的方式更为C++风格,但是虽然这通常是通过开关来完成的,但我更喜欢数组:
#include <iostream>
namespace foo {
enum Colors { BLUE = 0, RED, GREEN, SIZE_OF_ENUM };
static const char* ColorNames[] = { "blue", "red", "green" };
// statically check that the size of ColorNames fits the number of Colors
static_assert(sizeof(foo::ColorNames)/sizeof(char*) == foo::SIZE_OF_ENUM
, "sizes dont match");
} // foo
int main()
{
std::cout << foo::ColorNames[foo::BLUE] << std::endl;
return 0;
}
#包括
名称空间foo{
枚举颜色{蓝色=0,红色,绿色,大小为_enum};
静态常量字符*颜色名称[]={“蓝色”、“红色”、“绿色”};
//静态检查ColorNames的大小是否与颜色的数量相匹配
静态\u断言(sizeof(foo::ColorNames)/sizeof(char*)==foo::SIZE\u的\u枚举
,“尺寸不匹配”);
}//富
int main()
{
std::cout用宏实现一点魔法怎么样:
#include <iostream>
#include <string>
#include <vector>
// http://stackoverflow.com/questions/236129/how-to-split-a-string-in-c
std::vector<std::string> split(const std::string &text, char sep) {
std::vector<std::string> tokens;
int start = 0, end = 0;
while ((end = text.find(sep, start)) != std::string::npos) {
tokens.push_back(text.substr(start, end - start));
start = end + 1;
}
tokens.push_back(text.substr(start));
return tokens;
}
#define ENUM(name, ...)\
enum name \
{\
__VA_ARGS__\
};\
std::vector<std::string> name##Map = split(#__VA_ARGS__, ',');\
std::string toString(const name v) { return name##Map.at(v);}
ENUM(Color, Red,Green,Blue)
int main(int c, char**v)
{
std::cout << toString(Red) << toString(Blue);
return 0;//a.exec();
}
#包括
#包括
#包括
// http://stackoverflow.com/questions/236129/how-to-split-a-string-in-c
标准::向量拆分(常量标准::字符串和文本,字符sep){
std::向量标记;
int start=0,end=0;
while((end=text.find(sep,start))!=std::string::npos){
tokens.push_back(text.substr(start,end-start));
开始=结束+1;
}
tokens.push_back(text.substr(start));
归还代币;
}
#定义枚举(名称,…)\
枚举名\
{\
__瓦乌阿格斯__\
};\
std::vector name##Map=split(###VA_uargs_#,',')\
std::string toString(const name v){return name##Map.at(v)}
枚举(颜色、红色、绿色、蓝色)
int main(int c,字符**v)
{
std::cout我非常喜欢@Lol4t0的宏方法
我对其进行了扩展,使其能够从字符串转换枚举:
#include <iostream>
#include <string>
#include <vector>
// http://stackoverflow.com/questions/236129/how-to-split-a-string-in-c
std::vector<std::string> split(const std::string &text, char sep) {
std::vector<std::string> tokens;
int start = 0, end = 0;
while ((end = text.find(sep, start)) != std::string::npos) {
tokens.push_back(text.substr(start, end - start));
start = end + 1;
}
tokens.push_back(text.substr(start));
return tokens;
}
#define ENUM(name, ...)\
enum name\
{\
__VA_ARGS__\
};\
static const int name##Size = (sizeof((int[]){__VA_ARGS__})/sizeof(int));\
static const vector<string> name##ToStringMap = split(#__VA_ARGS__, ',');\
const string name##ToString(const name value)\
{\
return name##ToStringMap.at(value);\
};\
map<string, name> name##ToFromStringMap(...)\
{\
map<string, name> m;\
name args[name##Size] = { __VA_ARGS__ };\
\
int i;\
for(i = 0; i < name##Size; ++i)\
{\
m[name##ToString(args[i])] = args[i];\
}\
return m;\
};\
static map<string, name> name##FromStringMap = name##ToFromStringMap(__VA_ARGS__);\
const name name##FromString(const string value, const name defaultValue)\
{\
if(name##FromStringMap.count(value) == 0)\
{\
return defaultValue;\
}\
return name##FromStringMap[value];\
};
<我不是一个C++专家,所以让我知道你的想法或如何做得更好。< /P>它如何工作于C……反射?”CONQUAND QUANT:是的,你可以看到代码< EnUM>代码>类的反射。看看我的大小限制。这使成语有点好。如果忘记添加字符串,它不会产生错误…@ Matth。嗯。是的。构建类似这样的东西的唯一可靠方法可能是宏。我恐怕是这样。我一直认为这也是一种耻辱,我会很感激编译器在一旁构建函数。我发现的一种方法是使用宏,尽管这或多或少是内联函数。另一种方法是使用测试来确保lation对以前的类型有效(至少),然后依赖开发人员来思考:)@MatthieuM。我想真正的解决方案仍然是使用常量无序_map
。它可以屏蔽维护人员对枚举可能做的几乎所有事情,并在运行时防止误用,但有点昂贵。替换ColorNames[SIZE_OF_ENUM]
与ColorNames[]
并添加静态断言(sizeof(foo::ColorNames)/sizeof(char*)==foo::SIZE_OF_ENUM,“大小不匹配”)这是非常棒的!我很确定这可以用C++ 11个参数包做得更干净,所以在运行时你根本没有任何工作。C++被认为是消除了宏。我认为,这种方法的最佳解决方案也可以用包含间隙的枚举来使用。例如,红色= 0x01,绿色,蓝色=0x10,黄色。
ENUM(MyEnum, Value1, Value2)
void main()
{
string valueName = MyEnumToString(MyEnum::Value2);
MyEnum value = MyEnumFromString(valueName, MyEnum::Value1);
}