Общий метод отобразить имена перечисления значений

Существует ли способ отобразить название значения перечисления? скажите, что мы имеем:

enum fuits{
    APPLE,
    MANGO,
    ORANGE,
};

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

использование препроцессора

#define _PRINT_ENUM_STRING(x) #x

не будет работать, поскольку мы должны получить значение переменной 'x' и затем преобразовать Его для строкового представления. Это находится вообще возможно в c/C ++?

7
задан s_b 11 August 2010 в 06:52
поделиться

3 ответа

Вы можете использовать препроцессор для этого, я считаю, что этот метод называется 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 *) * large_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) , используя имя_ фрукта [PINEAPPLE_KEY] .

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

#define FRUIT_LIST X(APPLE) X(ORANGE)

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

7
ответ дан 7 December 2019 в 07:38
поделиться

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

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

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

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

Также проверьте этот вопрос , чтобы получить дополнительную информацию.

1
ответ дан 7 December 2019 в 07:38
поделиться

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

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

Он делает немного больше, чем просто выводит имена, но при необходимости его можно легко упростить до двух переключателей.

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

0
ответ дан 7 December 2019 в 07:38
поделиться