簡體   English   中英

在C中從String轉換為Enum

[英]Converting from String to Enum in C

是否有一種方便的方法來獲取字符串(由用戶輸入)並將其轉換為枚舉值? 在這種情況下,字符串將是枚舉值的名稱,如下所示:

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

因此,如果用戶給出了Day的名稱,則可以將其解析為相應的Enum值。

訣竅是,我有超過500個我正在使用的值,它們分布在多個枚舉中。

我知道c#中的Enum.Parse方法,所以在c中有這種形式嗎?

實現它的標准方法是:

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

您可以嘗試其他基本概念的變體。

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

如果你使用直C,那么就沒有“Enum.Parse”等價物。 您將要編寫自己的函數,將用戶的字符串與預定義的值與strcmp() ,然后返回相應的枚舉值。

另一種可能性是使用現有的“哈希映射”實現,或者自己滾動 - 例如,glib中的那個應該適合你: https//developer.gnome.org/glib/2.30/glib-Hash-Tables.html

哈希映射應該比對可能的枚舉值進行線性搜索更快,如果你有很多(例如,如果你做的不是一周中的幾天)。 一個好的哈希映射實現應該接近O(1)進行查找,而不是O(n)進行線性搜索。

但事實並非如此,但如果使用哈希函數,則可以設置枚舉的所有值以匹配一組哈希字符串。 如果您不關心區分大小寫,則可能必須使用更復雜的哈希。

這可能是您最好的解決方案,因為它的開銷低於strcmp(...)。 從字符串哈希中分配枚舉值不需要重復的字符串比較等...

這將是一個很好的解決方案:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM