Подтвердить что ты не робот

Как получить имя элемента перечисления из его значения

Я объявил тип перечисления как это,

enum WeekEnum
{
Mon = 0;
Tue = 1;
Wed = 2;
Thu = 3;
Fri = 4;
Sat = 5;
Sun = 6;
};

Как я могу получить имя элемента "Mon, Tue и т.д.", когда у меня уже есть значение элемента "0, 1 и т.д.".

У меня уже есть функция как

Log(Today is "2", enjoy! );

И теперь я хочу, чтобы результат ниже

Сегодня Wed, наслаждайтесь

4b9b3361

Ответ 1

Вы не можете напрямую, enum в С++ не похожи на Java перечисления.

Обычный подход заключается в создании std::map<WeekEnum,std::string>.

std::map<WeekEnum,std::string> m;
m[Mon] = "Monday";
//...
m[Sun] = "Sunday";

Ответ 2

Перечисление является чем-то вроде инверсного массива. Я считаю, что вы хотите:

const char * Week[] = { "", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };  // The blank string at the beginning is so that Sunday is 1 instead of 0.
cout << "Today is " << Week[2] << ", enjoy!";  // Or whatever you'de like to do with it.

Ответ 3

Нет, у вас нет возможности получить "имя" из значения в C++, потому что все символы отбрасываются во время компиляции.

Вам может понадобиться этот способ X Макросы

Ответ 4

Вы можете определить оператор, который выполняет вывод.

std::ostream& operator<<(std::ostream& lhs, WeekEnum e) {
    switch(e) {
    case Monday: lhs << "Monday"; break;
    .. etc
    }
    return lhs;
}

Ответ 5

Вот еще один полезный трюк для определения enum с помощью X Macro:

#include <iostream>

#define WEEK_DAYS \
X(MON, "Monday", true) \
X(TUE, "Tuesday", true) \
X(WED, "Wednesday", true) \
X(THU, "Thursday", true) \
X(FRI, "Friday", true) \
X(SAT, "Saturday", false) \
X(SUN, "Sunday", false)

#define X(day, name, workday) day,
enum WeekDay : size_t
{
    WEEK_DAYS
};
#undef X

#define X(day, name, workday) name,
char const *weekday_name[] =
{
    WEEK_DAYS
};
#undef X

#define X(day, name, workday) workday,
bool weekday_workday[]
{
    WEEK_DAYS
};
#undef X

int main()
{
    std::cout << "Enum value: " << WeekDay::THU << std::endl;
    std::cout << "Name string: " << weekday_name[WeekDay::THU] << std::endl;
    std::cout << std::boolalpha << "Work day: " << weekday_workday[WeekDay::THU] << std::endl;

    WeekDay wd = SUN;
    std::cout << "Enum value: " << wd << std::endl;
    std::cout << "Name string: " << weekday_name[wd] << std::endl;
    std::cout << std::boolalpha << "Work day: " << weekday_workday[wd] << std::endl;

    return 0;
}

Живая демоверсия: https://ideone.com/bPAVTM

Выходы:

Enum value: 3
Name string: Thursday
Work day: true
Enum value: 6
Name string: Sunday
Work day: false

Ответ 6

Как я могу получить имя элемента "Mon, Tue и т.д.", когда у меня уже есть значение позиции "0, 1 и т.д."

На каком-то старом C-коде (довольно давно) я нашел код, аналогичный:

std::string weekEnumToStr(int n)
{
   std::string s("unknown");
   switch (n)
   {
   case 0: { s = "Mon"; } break;
   case 1: { s = "Tue"; } break;
   case 2: { s = "Wed"; } break;
   case 3: { s = "Thu"; } break;
   case 4: { s = "Fri"; } break;
   case 5: { s = "Sat"; } break;
   case 6: { s = "Sun"; } break;
   }
   return s;
}

Con: Это устанавливает "патологическую зависимость" между значениями перечисления и функцией... что означает, что если вы измените перечисление, вы должны изменить соответствующую функцию. Я полагаю, это справедливо даже для std:: map.

Я смутно помню, что мы нашли утилиту для генерации кода функции из кода перечисления. Длина таблицы enum выросла до нескольких сотен... и в какой-то момент это, возможно, выбор звука для написания кода для написания кода.


Примечание -

во встроенном усилении системы моя команда заменила множество таблиц (100+?) строк с нулевым завершением, используемых для сопоставления значений enum int с их текстовыми строками.

Проблема с таблицами заключалась в том, что значение вне диапазона часто не замечалось, потому что многие из этих таблиц были собраны в одну область кода/памяти, так что значение вне диапазона достигло конца именованной таблицы ( s) и возвратил строку с нулевым завершением из некоторой последующей таблицы.

Использование оператора function-with-switch также позволило нам добавить утверждение в предложение по умолчанию коммутатора. Утверждения обнаружили еще несколько ошибок кодирования во время теста, и наши утверждения были привязаны к статическому-ram-system-log, который наши поисковые технологии могли искать.

Ответ 7

У меня был отличный успех с техникой, которая напоминает макросы X, на которые указывает @RolandXu. Мы также сильно использовали оператор строзинга. Этот метод смягчает кошмар обслуживания, когда у вас есть домен приложения, где элементы отображаются как строки, так и числовые токены.

Это особенно удобно, когда доступна машиночитаемая документация, так что строки макроса X (...) могут быть автоматически сгенерированы. Новая документация немедленно привела бы к последовательному обновлению программы, охватывающему строки, перечисления и словари, переводящие их между собой в обоих направлениях. (Мы имели дело с токенами PCL6).

И хотя код препроцессора выглядит довольно уродливым, все эти технические возможности могут быть скрыты в заголовочных файлах, которые больше не нужно трогать, а также исходные файлы. Все безопасно. Единственное, что изменяется, это текстовый файл, содержащий все строки X (...), и это возможно сгенерировано автоматически.

Ответ 8

Если вы знаете фактические метки перечисления, соотнесенные с их значениями, вы можете использовать контейнеры и С++ 17 std::string_view для быстрого доступа к значениям и их строковым представлениям с помощью оператора [ ], отслеживая его самостоятельно. std::string_view будет выделять память только при создании. Они также могут быть обозначены static constexpr, если вы хотите, чтобы они были доступны во время выполнения для большей экономии производительности. Это небольшое консольное приложение должно быть довольно быстрым.

#include <iostream>
#include <string_view>
#include <tuple>    
int main() {
    enum class Weekdays { //default behavior starts at 0 and iterates by 1 per entry
        Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday
    };

    static constexpr std::string_view Monday    = "Monday";
    static constexpr std::string_view Tuesday   = "Tuesday";
    static constexpr std::string_view Wednesday = "Wednesday";
    static constexpr std::string_view Thursday  = "Thursday";
    static constexpr std::string_view Friday    = "Friday";
    static constexpr std::string_view Saturday  = "Saturday";
    static constexpr std::string_view Sunday    = "Sunday";
    static constexpr std::string_view opener    = "enum[";
    static constexpr std::string_view closer    = "] is ";
    static constexpr std::string_view semi      = ":";

    std::pair<Weekdays, std::string_view> Weekdays_List[] = {
        std::make_pair(Weekdays::Monday,    Monday),
        std::make_pair(Weekdays::Tuesday,   Tuesday),
        std::make_pair(Weekdays::Wednesday, Wednesday),
        std::make_pair(Weekdays::Thursday,  Thursday),
        std::make_pair(Weekdays::Friday,    Friday),
        std::make_pair(Weekdays::Saturday,  Saturday),
        std::make_pair(Weekdays::Sunday,    Sunday)
    };

    for (int i=0;i<sizeof(Weekdays_List)/sizeof(Weekdays_List[0]);i++) {
        std::cout<<opener<<i<<closer<<Weekdays_List[(int)i].second<<semi\
        <<(int)Weekdays_List[(int)i].first<<std::endl;
    }    
    return 0;
}

Вывод:

enum[0] is Monday:0
enum[1] is Tuesday:1
enum[2] is Wednesday:2
enum[3] is Thursday:3
enum[4] is Friday:4
enum[5] is Saturday:5
enum[6] is Sunday:6