2013-08-06 105 views
3

我有一个枚举,其中包含数百个条目。按名称获取枚举值

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

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

+3

不,不是那样的。另外,你所说的不是C. – Ryan

+0

避免它的方法是使用一个实际的表格。 – Ryan

+0

在这个意义上的实际表?考虑这两个c/cpp。 –

回答

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-宏来定义的颜色列表。这避免了两次定义列表。下面是使用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 
+0

喜欢这个解决方案!在“颜色(黄色)”语句之后立即取消定义“Color(x)”是否是一个好主意,以防止在代码的其他部分产生意外结果? – Floris

+1

加入 - 谢谢:-) –

0

这是一个黑客位,但如果您使用的是纯C,你可以做到以下几点:

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

然后你就可以通过循环阵列上,直到找到一个匹配找到匹配的字符串:

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

+1

如果您使用的是“std: :map'根本没有理由涉及预处理器,只需将它们设置为'colorMap [“Red”] = Red;'。 –

+1

当然,但现在'红'出现三次而不是两次。 – paddy

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 

而且走另一条路:

​​

编辑

如果您正在使用C++,那么,使用X-macr Ø对水稻的回答是:

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 
}; 

...或什么的。那不是我的语言。