我有一个枚举,其中包含数百个条目。
我将枚举的值作为字符串。有没有办法将字符串转换为枚举值?否则,我将最终使用数百个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; // i.e enumtype::stringVariable
在这里的许多帖子中,我们可以使用地图,但在构建地图时,我们最终会使用数百个if
。
有什么方法可以避免这种情况吗?
答案 0 :(得分:6)
这是一种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
答案 1 :(得分:4)
使用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<string, enum Colors> colorMap;
void InitColorMap()
{
#define X(name) colorMap[#name] = name;
LIST_OF_COLORS
#undef X
}
或者,从this answer窃取,在C ++ 11中:
static std::map<string, enum Colors> colorMap =
{
#define X(name) { #name, name },
LIST_OF_COLORS
#undef X
};
......或者其他什么。那不是我的语言。
答案 2 :(得分:0)
这有点像黑客攻击,但如果你使用纯C,你可以做以下事情:
char* stringArray[]={"Red", "Green", "Blue", "Yellow"};
然后,您可以通过循环遍历数组找到匹配的字符串,直到找到匹配项:
for(ii = 0; ii < size(stringArray); ii++) {
if (strcmp(inputString, stringArray[ii]) == 0) {
// you found it!
}
}
答案 3 :(得分:0)
目前尚不清楚您是否在使用C或C ++。
对此进行排序的一种方法是使用带有stringize运算符的宏。像这样:
#define RegisterColor(c) colorMap[#c] = (c)
在这种情况下,我假设像C ++ map
:
enum Colors { .... };
static std::map<string, enum Colors> colorMap;
void InitColorMap()
{
RegisterColor(Red);
RegisterColor(Green);
RegisterColor(Blue);
RegisterColor(Yellow);
// ...
}
有一点重复,但如果你需要enum
,你无法避免。
使用您自己的数据结构在C中使用相同的原理很容易。