开发者

Generic method to display enum value names

Is there a way to display the name of an enum's value? say we have:

enum fuits{
    APPLE,
    MANGO,
    ORANGE,
};

main(){
enum fruits xFruit = MANGO;
...
printf("%s",_PRINT_ENUM_STRING(xFruit));
...
}

using the preprocessor

#define _PRINT_ENUM_STRING(x) #x

won't work as we need to get the value of the variable 'x' and then convert It开发者_如何学C to string. Is this at all possible in c/C++?


You could use the preprocessor to do this, I believe this technique is called X-Macros:

/* fruits.def */
X(APPLE)
X(MANGO)
X(ORANGE)

/* file.c */
enum fruits {
#define X(a) a,
#include "fruits.def"
#undef X
};

const char *fruit_name[] = {
#define X(a) #a,
#include "fruits.def"
#undef X
};

Note that the last entry includes a trailing comma, which is allowed in C99 (but not in C89). If that is a problem you can add sentinal values. It is also possible to make the macro more complicated by giving multiple arguments for custom names or enum values, etc:

X(APPLE, Apple, 2)
#define X(a,b,c) a = c,        /* in enum */
#define X(a,b,c) [c] = #b,     /* in name array */

Limitations: You cannot have negative constants and your array is sizeof (char *) * largest_constant. But you could work around both by using an extra lookup table:

int map[] = {
#define X(a,b,c) c,
#include "fruits.def"
#undef X
};

This doesn't work of course. What does work is generating an extra set of enum constants as keys for the names:

enum fruits {
#define X(a,b,c) a ## _KEY,
#include "fruits.def"
#undef X
#define X(a,b,c) a = c,
#include "fruits.def"
#undef X
};

Now you can find the name of X(PINEAPPLE, Pineapple, -40) by using fruit_name[PINEAPPLE_KEY].

People noted that they didn't like the extra include file. You don't need this extra file, you also use a #define. This may be more appropriate for small lists:

#define FRUIT_LIST X(APPLE) X(ORANGE)

And replace #include "fruits.def with FRUIT_LIST in the previous examples.


You can use a mapping in this case.

char *a[10] = { "APPLE","MANGO","ORANGE"};

printf("%s",a[xFruit]);

Yes the preprocessor won't work unless you provide the exact enum -value.

Also check this question for more insights.


I've used preprocessor programming successfully to get a macro of this kind:

DEFINE_ENUM(Fruits, (Apple)(Mango)(Orange));

It does a tad more than just printing the names, but it could easily be simplified to 2 switches if necessary.

It's based on Boost.Preprocessor facilities (notably BOOST_PP_SEQ_FOREACH) which is a must have for preprocessor programming, and I find it much more elegant than the X facility and its file reinclusion system.


 public enum LDGoalProgressUpdateState
    {

    [Description("Yet To Start")]
    YetToStart = 1,
    [Description("In Progress")]
    InProgress = 2,
    [Description("Completed")]
    Completed = 3
}


    var values = (ENUMList[])Enum.GetValues(typeof(ENUMList));
    var query = from name in values
                select new EnumData//EnumData is a Modal or Entity
                {
                    ID = (short)name,
                    Name = GetEnumDescription(name)//Description of Particular Enum Name
                };
    return query.ToList();

region HelperMethods

public static string GetEnumDescription(Enum value) { FieldInfo fi = value.GetType().GetField(value.ToString()); DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false); if (attributes != null && attributes.Length > 0) return attributes[0].Description; else return value.ToString(); } #endregion
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜