我声明了一个枚举类型,
enum WeekEnum
{
Mon = 0;
Tue = 1;
Wed = 2;
Thu = 3;
Fri = 4;
Sat = 5;
Sun = 6;
};
当我已经拥有项目值“0、1 等”时,如何获取项目名称“周一、周二等”?
我已经有这样的功能
Log(Today is "2", enjoy! );
现在我想要下面的输出
今天是星期三,好好享受
你不能直接,enum
在 C++ 中不像 Java 枚举。
通常的方法是创建一个std::map<WeekEnum,std::string>
.
std::map<WeekEnum,std::string> m;
m[Mon] = "Monday";
//...
m[Sun] = "Sunday";
这是使用 X 宏定义枚举的另一个巧妙技巧:
#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
不,您无法从 C++ 中的值中获取“名称”,因为所有符号在编译过程中都会被丢弃。
你可能需要这种方式X Macros
枚举类似于逆数组。我相信你想要的是这样的:
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.
您可以定义执行输出的运算符。
std::ostream& operator<<(std::ostream& lhs, WeekEnum e) {
switch(e) {
case Monday: lhs << "Monday"; break;
.. etc
}
return lhs;
}
当我已经拥有项目值“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;
}
缺点:这在枚举值和函数之间建立了“病态依赖性”......这意味着如果您更改枚举,则必须更改函数以匹配。我想即使对于 std::map 也是如此。
我依稀记得我们找到了一个从枚举代码生成函数代码的实用程序。枚举表的长度已经增长到数百……在某些时候,编写代码来编写代码可能是一个不错的选择。
笔记 -
在嵌入式系统增强工作中,我的团队替换了许多用于将枚举 int 值映射到其文本字符串的空终止字符串表(100+?)。
这些表的问题是超出范围的值通常不会被注意到,因为这些表中的许多都被收集到一个代码/内存区域中,因此超出范围的值超出了指定的表末端和从某个后续表中返回一个以空字符结尾的字符串。
使用 function-with-switch 语句还允许我们在 switch 的默认子句中添加一个断言。断言在测试期间发现了更多的编码错误,我们的断言被绑定到我们的现场技术人员可以搜索的静态内存系统日志中。
我使用类似于@RolandXu 指出的 X 宏的技术取得了巨大的成功。我们也大量使用了 stringize 运算符。当您的应用程序域中的项目同时显示为字符串和数字标记时,该技术可以减轻维护的噩梦。
当机器可读的文档可用时,它会特别方便,以便可以自动生成宏 X(...) 行。新的文档将立即导致一致的程序更新,涵盖字符串、枚举和在它们之间双向转换的字典。(我们正在处理 PCL6 令牌)。
虽然预处理器代码看起来很丑陋,但所有这些技术细节都可以隐藏在头文件中,永远不必再触及,源文件也一样。一切都是类型安全的。唯一改变的是一个包含所有 X(...) 行的文本文件,这可能是自动生成的。
在 GCC 上,它可能看起来像这样:
const char* WeekEnumNames [] = {
[Mon] = "Mon",
[Tue] = "Tue",
[Wed] = "Wed",
[Thu] = "Thu",
[Fri] = "Fri",
[Sat] = "Sat",
[Sun] = "Sun",
};
如果您知道与它们的值相关的实际枚举标签,则可以使用容器和 C++17std::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
我更喜欢的解决方案是像这样混合数组和 ostream:
std::ostream& operator<<(std::ostream& lhs, WeekEnum e) {
static const std::array<std::string, 7> WEEK_STRINGS = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" };
return lhs << WEEK_STRINGS[static_cast<WeekEnum>(e)]
}
cout << "Today is " << WeekEnum::Monday;
我还建议使用enum class
而不是enum
.