按名称获取枚举值

我有一个枚举,其中包含数百个条目。

我将枚举的值作为字符串。 有没有办法将字符串转换为枚举值? 否则,我将最终使用数百个if语句。

考虑

enum Colors { Red, Green, Blue, Yellow ... } there are more than 100 entries 

我将在字符串变量中获得"Red"

 String color = "Red"; // "Red" would be generated dynamically. 

通常我们通过以下方式访问枚举: Colors::RedColors::Blue等…有什么方法可以让我们以这样的方式访问它:

 Colors::color; // ie enumtype::stringVariable 

在这里的许多post中,我们可以使用地图,但在构建地图时,我们最终会使用数百个if

有什么方法可以避免这种情况吗?

这是一种C方式,类似于Paddy的C ++地图。 宏保证名称和相应的枚举绑定在一起。

 enum Colors { NoColor, Red, Green, Blue, Yellow }; enum Colors get_color(const char *s) { const struct { char *name; enum Colors color; } colormap[] = { #define Color(x) {#x, x} Color(Red), Color(Green), Color(Blue), Color(Yellow) #undef Color }; for (size_t i = 0; i < sizeof colormap / sizeof colormap[0]; ++i) { if (!strcmp(s, colormap[i].name)) { return colormap[i].color; } } return NoColor; } 

编辑正如@ sh1在评论中提出的(现在已经过去了),您可以使用X-macro来定义颜色列表。 这避免了两次定义列表。 以下是使用X-macro重写的上述示例 - 感谢sh1提示:

 #define COLORS X(Red), X(Green), X(Blue), X(Yellow), enum Colors { NoColor, #define X(x) x COLORS #undef X }; enum Colors get_color(const char *s) { const struct { char *name; enum Colors color; } colormap[] = { #define X(x) {#x, x} COLORS #undef X }; ...etc 

使用X-macro技术。 几乎直接从维基百科转录:

 #define LIST_OF_COLORS \ X(Red) \ X(Green) \ X(Blue) \ X(Yellow) #define X(name) name, enum Colors { LIST_OF_COLORS }; #undef X #define X(name) #name, char const * const ColorName[] = { LIST_OF_COLORS }; #undef X 

因为枚举会自动指定从零开始计数的值,并且在创建名称数组时我们不会以不同的顺序意外重复列表,使用枚举作为ColorName数组的索引将始终直接指向相应的单词,并且您在该方向上映射时不必搜索。 所以:

 printf("%s\n", ColorName[Red]); 

将打印:

 Red 

走另一条路:

 enum Color strtoColor(char const *name) { for (int i = 0; i < sizeof(ColorName) / sizeof(*ColorName); i++) if (strcmp(ColorName[i], name) == 0) return (enum Color)i; return -1; } 

编辑

如果您正在使用C ++,那么,在paddy的答案中使用X-macro:

 static std::map colorMap; void InitColorMap() { #define X(name) colorMap[#name] = name; LIST_OF_COLORS #undef X } 

或者,从这个答案中窃取,在C ++ 11中:

 static std::map colorMap = { #define X(name) { #name, name }, LIST_OF_COLORS #undef X }; 

... 管他呢。 那不是我的语言。

这有点像黑客,但如果您使用的是纯C,您可以执行以下操作:

 char* stringArray[]={"Red", "Green", "Blue", "Yellow"}; 

然后,您可以通过循环遍历数组找到匹配的字符串,直到找到匹配项:

 for(ii = 0; ii < size(stringArray); ii++) { if (strcmp(inputString, stringArray[ii]) == 0) { // you found it! } } 

目前尚不清楚你是否在使用C或C ++。

解决这个问题的一种方法是使用带有stringize运算符的宏。 像这样的东西:

 #define RegisterColor(c) colorMap[#c] = (c) 

在这种情况下,我假设像C ++ map

 enum Colors { .... }; static std::map colorMap; void InitColorMap() { RegisterColor(Red); RegisterColor(Green); RegisterColor(Blue); RegisterColor(Yellow); // ... } 

有一点重复,但如果你需要enum你无法避免。

使用您自己的数据结构在C中使用相同的原理很容易。