在C中从String转换为Enum

时间:2013-05-30 19:50:14

标签: c string enums

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

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

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

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

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

6 个答案:

答案 0 :(得分:12)

实现它的标准方法是:

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

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

答案 1 :(得分:3)

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

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

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

在main.c中:

#include <stdio.h>

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

您可以尝试其他基本想法的变体。

答案 2 :(得分:2)

警告,这是完全黑客攻击。您可以使用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;
}

答案 3 :(得分:1)

如果您使用的是直线C,则不存在“Enum.Parse”等效值。您将要编写自己的函数,将用户的字符串与预定义的值与strcmp()进行比较,然后返回相应的枚举值。

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

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

答案 4 :(得分:1)

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

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

答案 5 :(得分:0)

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

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;
 }
相关问题