简体   繁体   中英

How can I convert between enum and cstring without map?

I've seen this answered before but using map or vectors, but I can't use outside libraries for my project, so I need to figure out another way. For converting to a cstring I'm using a function with a switch case and it works, but for converting from a cstring to the enum isn't going as planned.

The method I came up with for converting a cstring to an enum is to first cast the enum to an int (none, first, second, etc.. becomes 0, 1, 2, etc...) so that I can use a for loop to iterate through the different enums. Next, using the enum to cstring function, I compare the string passed in to the string given by the converting function. If they are equal, the enum is set. This seems like a pretty convoluted way to do this, and unsurprisingly, I can't get it working.

Here's all my test code, the setType function is where things go wrong.

enum type { none, first, second, third, fourth };

const char* typeName(type name);
type setType(char* name);                   // trouble here
int myStrComp(const char *str1, const char *str2);  // compare cstrings

int main() {                                // test the function
    char testName[] = "second";
    type testType = setType(testName);
    std::cout << typeName(testType) << std::endl;   // should print "second"
}

const char* typeName(type name) {           // convert enum to cstring
    switch (name) {
    case none:      return '\0';        break;
    case first:     return "first";     break;
    case second:    return "second";    break;
    case third:     return "third";     break;
    case fourth:    return "fourth";    break;
    }
}

type setType(char* name) {
    type temp;
    for (int i = 0; i < 4; i++) {       // I know, inefficient
        temp = static_cast<type>(i);    // but there's only 5 to check
        if (myStrComp(name, typeName(temp)) == 0) {
            return temp;
        }
    }
    return none;    // shouldn't get here
}

int myStrComp(const char *str1, const char *str2) {
    while (*str1 == *str2) {
        if (!*str1) {
            return 0;           // strings are equal
        }
        str1++;
        str2++;
    }
    return *str1 - *str2;   // how different are they alphabetically
}
case none:      return '\0';        break;

This has single quotes, so it returns character \\0 , which as an integer is equal to 0. When converted to pointer, this is a null pointer . When you try to dereference a null pointer in myStrComp() , an access violation happens.

Instead, you can use return ""; to return an empty string.

Possible way to simplify typeName is to use an array:

const char* typeName[] = {"", "first", "second", "third", "fourth"};
if (myStrComp(name, typeName[i]) == 0) 

(This will cause access violation if i is out of bounds.)

To answer your question , you can associate enum s with text by using a lookup table:

struct Entry
{
  type  enum_type;
  const char * enum_text;
};

Entry enum_conversion_table[] =
{
    {none, "none"},
    {first, "first"},
    {second, "second"},
    {third,  "third"},
    {fourth, "fourth"},
};
static const size_t conversion_table_capacity =
    sizeof(conversion_table) / sizeof(conversion_table[0]);

Converting from enum to text:

  1. Search the table for an entry with the key enum.
  2. Return a pointer to the text field of the entry, if found, or nullptr if not found.

Converting from text to enum :

  1. Search the table for an entry with the key enum text.
  2. Return the enum value if found, or create another enum value for "unknown" and return that.

This technique:
1. Doesn't use any libraries.
2. The data can be placed into the constant data section and stored into read-only memory.
3. The code can access the data directly.
4. The data is initialized before main() .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM