按名称获取枚举值
我有一个枚举,其中包含数百个条目。
我将枚举的值作为字符串。 有没有办法将字符串转换为枚举值? 否则,我将最终使用数百个if语句。
考虑
enum Colors { Red, Green, Blue, Yellow ... } there are more than 100 entries
我将在字符串变量中获得"Red"
,
String color = "Red"; // "Red" would be generated dynamically.
通常我们通过以下方式访问枚举: Colors::Red
, Colors::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中使用相同的原理很容易。