5

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

我将枚举的值作为字符串获取。有没有办法将字符串转换为枚举值?否则,我最终将使用数百个 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

在这里的许多帖子中,我们都可以使用 map ,但是在构建 map 时,我们最终会使用数百个ifs。

有没有办法避免这种情况?

4

4 回答 4

7

这是一种 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 宏来定义颜色列表。这避免了两次定义列表。这是使用 X 宏重写的上述示例 - 感谢 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
于 2013-08-06T18:01:47.393 回答
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

因为枚举会自动分配从零开始计数的值,并且我们在创建名称数组时不会不小心以不同的顺序重复列表,所以使用枚举作为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++,那么在稻田的回答中使用 X-macro:

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

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

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

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

于 2013-08-11T14:05:21.810 回答
0

这有点小技巧,但是如果您使用的是纯 C,则可以执行以下操作:

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

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

for(ii = 0; ii < size(stringArray); ii++) {
  if (strcmp(inputString, stringArray[ii]) == 0) {
    // you found it!
  }
}
于 2013-08-06T02:24:44.507 回答
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 中使用相同的原理很容易。

于 2013-08-06T02:24:47.043 回答