2010年11月14日 星期日

Print enumeration name in C, C++

Print out enumeration name as string is useful for debugging, but I does not how to do it until I read a sample code from MSDN on last week. That’s really shame for being an engineer (害羞).

Pre-defined Enumeration

For pre-defined enumeration, you can use macro ‘#' with enumeration name. This way was exists in C already, I cannot imaging that why I don’t know this before.

Here is a example to get NCM_* enumeration name:

const char * GetNCMStr(NETCON_MEDIATYPE type) {

    switch (type) {

        case NCM_NONE: return #NCM_NONE;

        case NCM_ISDN: return #NCM_ISDN;

        default: return “Unknown Type”;

    }

}

Of course you can use a macro to simplify the function.

#define CASE_ENTRY(_x)        \

    case (_x): return #(_x);

const char * GetNCMStr(NETCON_MEDIATYPE type) {

    switch (type) {

        CASE_ENTRY(NCM_NONE);

        CASE_ENTRY(NCM_ISDN);

        default: return “Unknown Type”;

    }

}

Although you still need to list all enumeration items you needed, but it’s easier than define a mapping string array and print out string from that array.

Your Own Enumeration

And here are some #define statements for you to create your own enumeration and corresponded conversion functions for getting name from value or getting value from name.

#define ENUM_BODY(name, value) \

    name = value,

#define AS_STRING_CASE(name, value) \

    case name: return #name;

#define FROM_STRING_CASE(name, value) \

    if (strcmp(str, #name) == 0) { return name; }

#define DEFINE_ENUM(name, list) \

    typedef enum { \

        list(ENUM_BODY) \

    } name; \

    const char * asString(name n) { \

        switch (n) { \

            list(AS_STRING_CASE) \

            default: return “”; \

        } \

    } \

    name fromString(const char * str) { \

        list(FROM_STRING_CASE) \

        return 0; /* assert? throw? */ \

    }

Now, we want to create a enumeration “Color” with item “RED”, “GREEN” and “BLUE”, we can simply doing this:

#define ENUM_LIST(_) \

    _(RED, 0) \

    _(GREEN, 1) \

    _(BLUE, 87)

DEFINE_ENUM(Color, ENUM_LIST)

Done. Now you have a enumeration “Color”, and you can use asString() function to get it’s name by value, and use fromString() function to get the value by name string.

Of course, you can modify the macro to support TCHAR.

沒有留言:

張貼留言