Ответ 1
Вы не можете напрямую, enum
в С++ не похожи на Java перечисления.
Обычный подход заключается в создании std::map<WeekEnum,std::string>
.
std::map<WeekEnum,std::string> m;
m[Mon] = "Monday";
//...
m[Sun] = "Sunday";
Я объявил тип перечисления как это,
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, наслаждайтесь
Вы не можете напрямую, enum
в С++ не похожи на Java перечисления.
Обычный подход заключается в создании std::map<WeekEnum,std::string>
.
std::map<WeekEnum,std::string> m;
m[Mon] = "Monday";
//...
m[Sun] = "Sunday";
Перечисление является чем-то вроде инверсного массива. Я считаю, что вы хотите:
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.
Нет, у вас нет возможности получить "имя" из значения в C++, потому что все символы отбрасываются во время компиляции.
Вам может понадобиться этот способ X Макросы
Вы можете определить оператор, который выполняет вывод.
std::ostream& operator<<(std::ostream& lhs, WeekEnum e) {
switch(e) {
case Monday: lhs << "Monday"; break;
.. etc
}
return lhs;
}
Вот еще один полезный трюк для определения 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
Как я могу получить имя элемента "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, который наши поисковые технологии могли искать.
У меня был отличный успех с техникой, которая напоминает макросы X, на которые указывает @RolandXu. Мы также сильно использовали оператор строзинга. Этот метод смягчает кошмар обслуживания, когда у вас есть домен приложения, где элементы отображаются как строки, так и числовые токены.
Это особенно удобно, когда доступна машиночитаемая документация, так что строки макроса X (...) могут быть автоматически сгенерированы. Новая документация немедленно привела бы к последовательному обновлению программы, охватывающему строки, перечисления и словари, переводящие их между собой в обоих направлениях. (Мы имели дело с токенами PCL6).
И хотя код препроцессора выглядит довольно уродливым, все эти технические возможности могут быть скрыты в заголовочных файлах, которые больше не нужно трогать, а также исходные файлы. Все безопасно. Единственное, что изменяется, это текстовый файл, содержащий все строки X (...), и это возможно сгенерировано автоматически.
Если вы знаете фактические метки перечисления, соотнесенные с их значениями, вы можете использовать контейнеры и С++ 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