#1
  1. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2004
    Posts
    51
    Rep Power
    10

    Convert string to enum in C


    I would like to have a list of commands defined as:

    Code:
    enum commands { AA, AB, AC, AD };
    And then have the ability to use the first two characters of a string to determine which command I need to execute using a switch statement.

    Code:
    strncpy(new_cmd, command, 2);
    switch((enum commands)new_cmd)
    {
    case AA : do something;
    case AB : something else;
    etc.
    }
    Is this possible with C? Is there a better way?
  2. #2
  3. Contributed User
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    Jun 2005
    Posts
    4,376
    Rep Power
    1871
    Not in any "automatic, free with the language" kind of way.

    Enums are basically #define AA 1 with some sense of type thrown in. By the time code generation happens, symbolic information is lost, and you're left with a constant of 1.

    There's nothing to stop you creating a string-to-enum lookup table.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2008
    Posts
    84
    Rep Power
    66
    This might be the C kernel programmer in me, but why not:

    Code:
    #ifndef _COMMANDS_
    #define _COMMANDS_
    #define AA "AA"
    #define AB "AB"
    #endif //_COMMANDS_
    
    char cmd_buffer[2];
    strncpy(cmd_buffer, in_string, 2)
    
    switch(cmd_buffer)
    {
      case AA: do something
      case AB: do something else
      default:  oops!
    }
    (Don't try to compile - that's code off the top of my head ;) )
  6. #4
  7. Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    Jun 2005
    Posts
    5,964
    Rep Power
    4852
    I think probably you don't understand what an enum is. You can think of it as a sort of compile time #define.

    Some member, such as AA, is not a string, "AA". It is a label that relates to some value. Think for a moment of a declaration such as
    Code:
    int AA = 0;
    The string, "AA", has no relationship with the variable which has been associated with the label (which is a string at heart) AA.

    An enum has some similarities with a #define.
    Code:
    #define AA 0
    will substitute the character '0' for every occurrence of the characters "AA" in the file, prior to compilation. I think that you can see that this would lead to problems, aside from the fact that 0 will not compare with "AA."

    An enum is not precisely the same thing. It's more akin to my first example. The enum will associate a value with each member of the enum. Normally the first member will receive the value 0 and the subsequent values will be incremented by 1. You may override this by making assignments in the definition of the enum.

    Now that you understand that the labels stored in the enum are nothing but aliases for integral values, consider the following code.
    Code:
    #include <stdio.h>
    
    enum commands {AA , AB, AC, AD};
    
    void AAfunc ()
    {
        printf ("AA command\n");
    }
    void ABfunc ()
    {
        printf ("AB command\n");
    }
    void ACfunc ()
    {
        printf ("AC command\n");
    }
    void ADfunc ()
    {
        printf ("AD command\n");
    }
    
    int main ()
    {
        int i;
        int match = 0;
        char command [3];
        char map [4][3] = {"AA", "AB", "AC", "AD"};
        printf ("%d, %c \n", AA, AA);
        fgets (command, 3, stdin);
        for (i = 0; i < 4; ++i)
        {
            if (strcmp (map [i], command) == 0)
            {
                match = 1;
                break;
            }
        }
        if (match)
        {
            switch (i)
            {
                case AA:
                    AAfunc ();
                    break;
                case AB:
                    ABfunc ();
                    break;
                case AC:
                    ACfunc ();
                    break;
                case AD:
                    ADfunc ();
                    break;
                default:
                    printf ("Invalid command\n");
                    break;
            }
        }else{
            printf ("Unknown or invalid command\n");
        }
    
    
        return 0;
    }
    Note that there is an overt effort to match up the integral values associated with the enum labels with the integral values forming an index into a set of character representations. This approach will work.

    Please note, also, that I would almost never choose to use this approach. I would be more inclined to use an array of function pointers.

    Note also there there are some minor differences regarding enums in C and enums in C++.

    The important point, however, is that NAMES used by the compiler to match VALUES are not equivalent to ASCII (or other textual forms) representations of those names.
    Write no code whose complexity leaves you wondering what the hell you did.
    Politically Incorrect DaWei on Pointers Grumpy on Exceptions

IMN logo majestic logo threadwatch logo seochat tools logo