Существует ли способ отобразить название значения перечисления? скажите, что мы имеем:
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 ++?
Вы можете использовать препроцессор для этого, я считаю, что этот метод называется 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
в предыдущих примерах.
В этом случае вы можете использовать отображение.
char *a[10] = { "APPLE","MANGO","ORANGE"};
printf("%s",a[xFruit]);
Да, препроцессор не будет работать, если вы не укажете точное значение enum.
Также проверьте этот вопрос , чтобы получить дополнительную информацию.
Я успешно использовал препроцессорное программирование, чтобы получить макрос такого типа:
DEFINE_ENUM(Fruits, (Apple)(Mango)(Orange));
Он делает немного больше, чем просто выводит имена, но при необходимости его можно легко упростить до двух переключателей.
Он основан на средствах Boost.Preprocessor (в частности, BOOST_PP_SEQ_FOREACH
), которые необходимы для программирования препроцессора, и я считаю его намного более элегантным, чем средство X
и его повторное включение файлов система.