按名称获取枚举值

Gok*_*rni 3 c enums

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

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

考虑

enum Colors { Red, Green, Blue, Yellow ... } there are more than 100 entries
Run Code Online (Sandbox Code Playgroud)

我将进入"Red"一个字符串变量,

String color = "Red"; // "Red" would be generated dynamically.
Run Code Online (Sandbox Code Playgroud)

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

Colors::color; // i.e enumtype::stringVariable
Run Code Online (Sandbox Code Playgroud)

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

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

Wil*_*ris 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;
}
Run Code Online (Sandbox Code Playgroud)


编辑 正如@ 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
Run Code Online (Sandbox Code Playgroud)


sh1*_*sh1 5

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

#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
Run Code Online (Sandbox Code Playgroud)

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

printf("%s\n", ColorName[Red]);
Run Code Online (Sandbox Code Playgroud)

将打印:

Red
Run Code Online (Sandbox Code Playgroud)

反过来说:

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;
}
Run Code Online (Sandbox Code Playgroud)

编辑

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

static std::map<string, enum Colors> colorMap;
void InitColorMap()
{
#define X(name) colorMap[#name] = name;
    LIST_OF_COLORS
#undef X
}
Run Code Online (Sandbox Code Playgroud)

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

static std::map<string, enum Colors> colorMap =
{
#define X(name) { #name, name },
    LIST_OF_COLORS
#undef X
};
Run Code Online (Sandbox Code Playgroud)

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