Converting from String to Enum in C

后端 未结 6 2001
我在风中等你
我在风中等你 2020-12-05 15:42

Is there a convienent way to take a string (input by user) and convert it to an Enumeration value? In this case, the string would be the name of the enumeration value, like

相关标签:
6条回答
  • 2020-12-05 16:05

    Warning, this is a total hack. You can use dlsym to do a lookup of a variable that is appropriately initialized. For this example to work, you have to compile to allow local symbols to be visible to the dynamic linker. With GCC, the option is -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;
    }
    
    0 讨论(0)
  • 2020-12-05 16:10

    The standard way to implement it is something along the lines of:

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

    The converse should be apparent.

    0 讨论(0)
  • 2020-12-05 16:14

    There isn't a direct way, but with C, you improvise. Here's an old trick. Purists may balk at this. But it's a way to manage this kind of stuff somewhat sanely. Uses some preprocessor tricks.

    In constants.h put in the following:

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

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

    You can try other variations of the basic idea.

    0 讨论(0)
  • 2020-12-05 16:18

    Not really, though if you use a hash function you can setup all of the values of your enum to match a set of hashed strings. You might have to use a more complicated hash if you don't care about case-sensitivity.

    This is probably your best solution, since it has lower overhead than strcmp (...). The assignment of an enum value from a string hash does not require repeated string comparisons, etc...

    0 讨论(0)
  • 2020-12-05 16:25

    That would be a good solution :

    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;
     }
    
    0 讨论(0)
  • 2020-12-05 16:28

    If you're using straight C, there isnt a "Enum.Parse" equivalent. You'll want to write your own function, comparing the user's string to pre-defined values with strcmp(), and then returning the appropriate enum value.

    Another possibility is using an existing "hash map" implementation, or rolling your own - for instance, the one in glib should work for you: https://developer.gnome.org/glib/2.30/glib-Hash-Tables.html

    A hash map should be faster than doing a linear search on the possible enum values, if you have a lot of them (for instance, if you were doing something other than the days of the week). A good hash map implementation should be close to O(1) for lookups, instead of O(n) for a linear search.

    0 讨论(0)
提交回复
热议问题