按名称获取枚举值

时间:2013-08-06 02:12:21

标签: c enums

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

我将枚举的值作为字符串。有没有办法将字符串转换为枚举值?否则,我将最终使用数百个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; // i.e enumtype::stringVariable

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

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

4 个答案:

答案 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中使用相同的原理很容易。