在C中从String转换为Enum

是否有一种方便的方法来获取字符串(由用户输入)并将其转换为枚举值? 在这种情况下,字符串将是枚举值的名称,如下所示:

enum Day { Sunday = 0, Monday = 1, ... } 

因此,如果用户给出了Day的名称,则可以将其解析为相应的Enum值。

诀窍是,我有超过500个我正在使用的值,它们分布在多个枚举中。

我知道c#中的Enum.Parse方法,所以在c中有这种forms吗?

实现它的标准方法是:

 typedef enum {value1, value2, value3, (...) } VALUE; const static struct { VALUE val; const char *str; } conversion [] = { {value1, "value1"}, {value2, "value2"}, {value3, "value3"}, (...) }; VALUE str2enum (const char *str) { int j; for (j = 0; j < sizeof (conversion) / sizeof (conversion[0]); ++j) if (!strcmp (str, conversion[j].str)) return conversion[j].val; error_message ("no such string"); } 

反过来应该是显而易见的。

没有直接的方法,但有了C,你即兴发挥。 这是一个老技巧。 纯粹主义者可能会对此犹豫不决。 但这是一种管理这种东西的方式。 使用一些预处理器技巧。

在constants.h中输入以下内容:

 CONSTANT(Sunday, 0) CONSTANT(Monday, 1) CONSTANT(Tuesday, 2) 

在main.c中:

 #include  #define CONSTANT(name, value) \ name = value, typedef enum { #include "constants.h" } Constants; #undef CONSTANT #define CONSTANT(name, value) \ #name, char* constants[] = { #include "constants.h" }; Constants str2enum(char* name) { int ii; for (ii = 0; ii < sizeof(constants) / sizeof(constants[0]); ++ii) { if (!strcmp(name, constants[ii])) { return (Constants)ii; } } return (Constants)-1; } int main() { printf("%s = %d\n", "Monday", str2enum("Monday")); printf("%s = %d\n", "Tuesday", str2enum("Tuesday")); return 0; } 

您可以尝试其他基本概念的变体。

警告,这完全是黑客攻击。 您可以使用dlsym查找已正确初始化的变量。 要使此示例起作用,必须进行编译以允许动态链接器可以看到本地符号。 使用GCC,选项是-rdynamic

 enum Day { SunDay, MonDay, TuesDay, WednesDay, ThursDay, FriDay, SaturDay }; enum Day Sunday = SunDay, Monday = MonDay, Tuesday = TuesDay, Wednesday = WednesDay, Thursday = ThursDay, Friday = FriDay, Saturday = SaturDay; int main () { const char *daystr = "Thursday"; void *h = dlopen(0, RTLD_NOW); enum Day *day = dlsym(h, daystr); if (day) printf("%s = %d\n", daystr, *day); else printf("%s not found\n", daystr); return 0; } 

但事实并非如此,但如果使用散列函数,则可以设置枚举的所有值以匹配一组散列字符串。 如果您不关心区分大小写,则可能必须使用更复杂的哈希。

这可能是您最好的解决方案,因为它的开销低于strcmp(…)。 从字符串哈希中分配枚举值不需要重复的字符串比较等…

如果你使用直C,那就不是“Enum.Parse”了。 您将要编写自己的函数,将用户的字符串与预定义的值与strcmp() ,然后返回相应的枚举值。

另一种可能性是使用现有的“哈希映射”实现,或者自己滚动 – 例如,glib中的那个应该适合你: https : //developer.gnome.org/glib/2.30/glib-Hash-Tables.html

哈希映射应该比对可能的枚举值进行线性搜索更快,如果你有很多(例如,如果你做的不是一周中的几天)。 一个好的哈希映射实现应该接近O(1)进行查找,而不是O(n)进行线性搜索。

这将是一个很好的解决方案:

 enum e_test { a, b, c, END }; enum e_test get_enum_value(char * val) { static char const * e_test_str[] = { "a", "b", "c" }; for (int i = 0; i < END; ++i) if (!strcmp(e_test_str[i], val)) return i; return END; }