2010-08-11 4 views
7

Есть ли способ отображения имени значения перечисления? сказать, что мы имеем:Общий метод отображения имен значений перечислений

enum fuits{ 
    APPLE, 
    MANGO, 
    ORANGE, 
}; 

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

используя препроцессор

#define _PRINT_ENUM_STRING(x) #x 

не будет работать, как нам нужно, чтобы получить значение переменной «х», а затем преобразовать его в строку. Возможно ли это в c/C++?

+0

Возможные дублируют http://stackoverflow.com/questions/3342726/c-print-out-enum-value-as-text –

+1

Это все FAQ по межтрубкам и, скорее всего, обман, хотя я не проверял. Ответ: нет, это не может быть сделано (без jumoing через обручи, такие как @Naveen предлагает и рискует выйти из синхронизации. Если вы готовы принять такой риск, то, по-видимому, использование этого решения будет использовать nunber. Это лучше, чем ничего , но это заманчивая судьба ...). – Mawg

+0

@Eugen Constantin Dinca Этот вопрос - только C++, в то время как OP здесь, похоже, хочет решение C. – schot

ответ

7

Вы можете использовать препроцессор, чтобы сделать это, я считаю, эта техника называется 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 
}; 

Обратите внимание, что последняя запись включает в себя Запятая, которая допускается в C99 (но не в C89). Если это проблема, вы можете добавить ценные значения. Кроме того, можно сделать макрос более сложным, давая несколько аргументов для пользовательских имен и значений перечислений и т.д.:

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

Ограничения: Вы не можете иметь отрицательные константы и ваш массив sizeof (char *) * largest_constant. Но вы могли бы работать вокруг и с помощью дополнительной таблицы подстановки:

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

Это не работает, конечно. Что работа порождает дополнительный набор enum констант в качестве ключей для имен:

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

Теперь вы можете найти имя X(PINEAPPLE, Pineapple, -40) с помощью fruit_name[PINEAPPLE_KEY].

Люди отметили, что им не понравился дополнительный файл include. Вам не нужен этот дополнительный файл, вы также используете #define. Это может быть более подходящим для небольших списков:

#define FRUIT_LIST X(APPLE) X(ORANGE) 

И заменить #include "fruits.def с FRUIT_LIST в предыдущих примерах.

+0

Это лучший способ узнать. Я использовал аналогичную технику для строк ошибок с помощью макроса с двумя аргументами X: 'X (name, desc)', где макрос расширился до кода ошибки (аналогично значениям errno) или описательной строки в зависимости от того, где файл списка ошибок был включен. –

+1

+1. Это почти превосходит мой обычный взлом определения перечисления в perl-скрипте, который записывает перечисление в файл .h и соответствующий массив преобразования в файл .c. Мой путь требует настраиваемого шага сборки, который легко сделать с помощью make, но сложнее в полной IDE. – RBerteig

+0

Мне это не нравится. Иногда может быть полезно, но я бы не злоупотреблял этим. Может быть, я буду использовать его для больших и часто измененных перечислений. Стоимость этого слишком велика. – adf88

1

Вы можете использовать отображение в этом случае.

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

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

Да, препроцессор не будет работать, если вы не предоставите точное значение enum.

Также проверьте this question для получения дополнительной информации.

0

Я использовал программирование препроцессора успешно, чтобы получить макрос вида:

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

Это делает чуть-чуть больше, чем просто печать имен, но это может быть легко упрощен до 2-х коммутаторов, если это необходимо.

Он основан на Boost.Preprocessor (особенно BOOST_PP_SEQ_FOREACH), который необходим для программирования препроцессора, и я нахожу его более элегантным, чем объект X и его система повторного ввода файлов.

-1

 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(); 

область 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

Это не похоже на C или C++, как указано в вопросе – jcoder

+0

Этот код относится к C# –

Смежные вопросы