如果我有这样的枚举
enum Errors
{ErrorA=0, ErrorB, ErrorC};
Run Code Online (Sandbox Code Playgroud)
然后我想打印到控制台
Errors anError = ErrorA;
cout<<anError;/// 0 will be printed
Run Code Online (Sandbox Code Playgroud)
但我想要的是文本"ErrorA",我可以不使用if/switch吗?
你有什么解决方案?
Sig*_*erm 56
使用地图:
#include <iostream>
#include <map>
#include <string>
enum Errors {ErrorA=0, ErrorB, ErrorC};
std::ostream& operator<<(std::ostream& out, const Errors value){
static std::map<Errors, std::string> strings;
if (strings.size() == 0){
#define INSERT_ELEMENT(p) strings[p] = #p
INSERT_ELEMENT(ErrorA);
INSERT_ELEMENT(ErrorB);
INSERT_ELEMENT(ErrorC);
#undef INSERT_ELEMENT
}
return out << strings[value];
}
int main(int argc, char** argv){
std::cout << ErrorA << std::endl << ErrorB << std::endl << ErrorC << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
使用线性搜索结构数组:
#include <iostream>
#include <string>
enum Errors {ErrorA=0, ErrorB, ErrorC};
std::ostream& operator<<(std::ostream& out, const Errors value){
#define MAPENTRY(p) {p, #p}
const struct MapEntry{
Errors value;
const char* str;
} entries[] = {
MAPENTRY(ErrorA),
MAPENTRY(ErrorB),
MAPENTRY(ErrorC),
{ErrorA, 0}//doesn't matter what is used instead of ErrorA here...
};
#undef MAPENTRY
const char* s = 0;
for (const MapEntry* i = entries; i->str; i++){
if (i->value == value){
s = i->str;
break;
}
}
return out << s;
}
int main(int argc, char** argv){
std::cout << ErrorA << std::endl << ErrorB << std::endl << ErrorC << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
使用开关/外壳:
#include <iostream>
#include <string>
enum Errors {ErrorA=0, ErrorB, ErrorC};
std::ostream& operator<<(std::ostream& out, const Errors value){
const char* s = 0;
#define PROCESS_VAL(p) case(p): s = #p; break;
switch(value){
PROCESS_VAL(ErrorA);
PROCESS_VAL(ErrorB);
PROCESS_VAL(ErrorC);
}
#undef PROCESS_VAL
return out << s;
}
int main(int argc, char** argv){
std::cout << ErrorA << std::endl << ErrorB << std::endl << ErrorC << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
Igo*_*Oks 25
使用具有匹配值的字符串数组或向量:
char *ErrorTypes[] =
{
"errorA",
"errorB",
"errorC"
};
cout << ErrorTypes[anError];
Run Code Online (Sandbox Code Playgroud)
编辑:上面的解决方案适用于枚举是连续的,即从0开始并且没有指定的值.它将与问题中的枚举完美配合.
要进一步证明enum不是从0开始的情况,请使用:
cout << ErrorTypes[anError - ErrorA];
Run Code Online (Sandbox Code Playgroud)
Phi*_*ipp 14
这是一个基于Boost.Preprocessor的示例:
#include <iostream>
#include <boost/preprocessor/punctuation/comma.hpp>
#include <boost/preprocessor/control/iif.hpp>
#include <boost/preprocessor/comparison/equal.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/seq/size.hpp>
#include <boost/preprocessor/seq/seq.hpp>
#define DEFINE_ENUM(name, values) \
enum name { \
BOOST_PP_SEQ_FOR_EACH(DEFINE_ENUM_VALUE, , values) \
}; \
inline const char* format_##name(name val) { \
switch (val) { \
BOOST_PP_SEQ_FOR_EACH(DEFINE_ENUM_FORMAT, , values) \
default: \
return 0; \
} \
}
#define DEFINE_ENUM_VALUE(r, data, elem) \
BOOST_PP_SEQ_HEAD(elem) \
BOOST_PP_IIF(BOOST_PP_EQUAL(BOOST_PP_SEQ_SIZE(elem), 2), \
= BOOST_PP_SEQ_TAIL(elem), ) \
BOOST_PP_COMMA()
#define DEFINE_ENUM_FORMAT(r, data, elem) \
case BOOST_PP_SEQ_HEAD(elem): \
return BOOST_PP_STRINGIZE(BOOST_PP_SEQ_HEAD(elem));
DEFINE_ENUM(Errors,
((ErrorA)(0))
((ErrorB))
((ErrorC)))
int main() {
std::cout << format_Errors(ErrorB) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
这里有一个讨论可能会有所帮助:Is there a simple way to conversion C++ enum to string?
更新: Here#sa 是 Lua 脚本,它为遇到的每个命名枚举创建一个运算符<<。这可能需要一些工作才能使其适用于不太简单的情况 [1]:
function make_enum_printers(s)
for n,body in string.gmatch(s,'enum%s+([%w_]+)%s*(%b{})') do
print('ostream& operator<<(ostream &o,'..n..' n) { switch(n){')
for k in string.gmatch(body,"([%w_]+)[^,]*") do
print(' case '..k..': return o<<"'..k..'";')
end
print(' default: return o<<"(invalid value)"; }}')
end
end
local f=io.open(arg[1],"r")
local s=f:read('*a')
make_enum_printers(s)
Run Code Online (Sandbox Code Playgroud)
鉴于此输入:
enum Errors
{ErrorA=0, ErrorB, ErrorC};
enum Sec {
X=1,Y=X,foo_bar=X+1,Z
};
Run Code Online (Sandbox Code Playgroud)
它生产:
ostream& operator<<(ostream &o,Errors n) { switch(n){
case ErrorA: return o<<"ErrorA";
case ErrorB: return o<<"ErrorB";
case ErrorC: return o<<"ErrorC";
default: return o<<"(invalid value)"; }}
ostream& operator<<(ostream &o,Sec n) { switch(n){
case X: return o<<"X";
case Y: return o<<"Y";
case foo_bar: return o<<"foo_bar";
case Z: return o<<"Z";
default: return o<<"(invalid value)"; }}
Run Code Online (Sandbox Code Playgroud)
所以这可能是你的一个开始。
[1] 不同或非命名空间范围中的枚举、带有包含 komma 的初始化表达式的枚举等。
每当定义枚举时,我都会使用字符串数组:
配置文件.h
#pragma once
struct Profile
{
enum Value
{
Profile1,
Profile2,
};
struct StringValueImplementation
{
const wchar_t* operator[](const Profile::Value profile)
{
switch (profile)
{
case Profile::Profile1: return L"Profile1";
case Profile::Profile2: return L"Profile2";
default: ASSERT(false); return NULL;
}
}
};
static StringValueImplementation StringValue;
};
Run Code Online (Sandbox Code Playgroud)
配置文件.cpp
#include "Profile.h"
Profile::StringValueImplementation Profile::StringValue;
Run Code Online (Sandbox Code Playgroud)
如果您愿意enum在外部文件中列出您的条目,您可以使用更简单的预处理器技巧。
/* file: errors.def */
/* syntax: ERROR_DEF(name, value) */
ERROR_DEF(ErrorA, 0x1)
ERROR_DEF(ErrorB, 0x2)
ERROR_DEF(ErrorC, 0x4)
Run Code Online (Sandbox Code Playgroud)
然后在源文件中,您将该文件视为包含文件,但您可以定义要ERROR_DEF执行的操作。
enum Errors {
#define ERROR_DEF(x,y) x = y,
#include "errors.def"
#undef ERROR_DEF
};
static inline std::ostream & operator << (std::ostream &o, Errors e) {
switch (e) {
#define ERROR_DEF(x,y) case y: return o << #x"[" << y << "]";
#include "errors.def"
#undef ERROR_DEF
default: return o << "unknown[" << e << "]";
}
}
Run Code Online (Sandbox Code Playgroud)
如果您使用某些源浏览工具(如 cscope),则必须让它知道外部文件。
此解决方案不需要您使用任何数据结构或创建不同的文件。
基本上,您在 #define 中定义所有枚举值,然后在运算符 << 中使用它们。与@jxh的答案非常相似。
最终迭代的 ideone 链接:http://ideone.com/hQTKQp
完整代码:
#include <iostream>
#define ERROR_VALUES ERROR_VALUE(NO_ERROR)\
ERROR_VALUE(FILE_NOT_FOUND)\
ERROR_VALUE(LABEL_UNINITIALISED)
enum class Error
{
#define ERROR_VALUE(NAME) NAME,
ERROR_VALUES
#undef ERROR_VALUE
};
inline std::ostream& operator<<(std::ostream& os, Error err)
{
int errVal = static_cast<int>(err);
switch (err)
{
#define ERROR_VALUE(NAME) case Error::NAME: return os << "[" << errVal << "]" #NAME;
ERROR_VALUES
#undef ERROR_VALUE
default:
// If the error value isn't found (shouldn't happen)
return os << errVal;
}
}
int main() {
std::cout << "Error: " << Error::NO_ERROR << std::endl;
std::cout << "Error: " << Error::FILE_NOT_FOUND << std::endl;
std::cout << "Error: " << Error::LABEL_UNINITIALISED << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
Error: [0]NO_ERROR
Error: [1]FILE_NOT_FOUND
Error: [2]LABEL_UNINITIALISED
Run Code Online (Sandbox Code Playgroud)
这样做的一个好处是,如果您认为需要,您还可以为每个错误指定自己的自定义消息:
#include <iostream>
#define ERROR_VALUES ERROR_VALUE(NO_ERROR, "Everything is fine")\
ERROR_VALUE(FILE_NOT_FOUND, "File is not found")\
ERROR_VALUE(LABEL_UNINITIALISED, "A component tried to the label before it was initialised")
enum class Error
{
#define ERROR_VALUE(NAME,DESCR) NAME,
ERROR_VALUES
#undef ERROR_VALUE
};
inline std::ostream& operator<<(std::ostream& os, Error err)
{
int errVal = static_cast<int>(err);
switch (err)
{
#define ERROR_VALUE(NAME,DESCR) case Error::NAME: return os << "[" << errVal << "]" #NAME <<"; " << DESCR;
ERROR_VALUES
#undef ERROR_VALUE
default:
return os << errVal;
}
}
int main() {
std::cout << "Error: " << Error::NO_ERROR << std::endl;
std::cout << "Error: " << Error::FILE_NOT_FOUND << std::endl;
std::cout << "Error: " << Error::LABEL_UNINITIALISED << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
Error: [0]NO_ERROR; Everything is fine
Error: [1]FILE_NOT_FOUND; File is not found
Error: [2]LABEL_UNINITIALISED; A component tried to the label before it was initialised
Run Code Online (Sandbox Code Playgroud)
如果您喜欢使错误代码/描述非常具有描述性,您可能不希望它们出现在生产版本中。关闭它们以便仅打印值很容易:
inline std::ostream& operator<<(std::ostream& os, Error err)
{
int errVal = static_cast<int>(err);
switch (err)
{
#ifndef PRODUCTION_BUILD // Don't print out names in production builds
#define ERROR_VALUE(NAME,DESCR) case Error::NAME: return os << "[" << errVal << "]" #NAME <<"; " << DESCR;
ERROR_VALUES
#undef ERROR_VALUE
#endif
default:
return os << errVal;
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
Error: 0
Error: 1
Error: 2
Run Code Online (Sandbox Code Playgroud)
如果是这种情况,找到错误号 525 将是一个 PITA。我们可以像这样手动指定初始枚举中的数字:
#define ERROR_VALUES ERROR_VALUE(NO_ERROR, 0, "Everything is fine")\
ERROR_VALUE(FILE_NOT_FOUND, 1, "File is not found")\
ERROR_VALUE(LABEL_UNINITIALISED, 2, "A component tried to the label before it was initialised")\
ERROR_VALUE(UKNOWN_ERROR, -1, "Uh oh")
enum class Error
{
#define ERROR_VALUE(NAME,VALUE,DESCR) NAME=VALUE,
ERROR_VALUES
#undef ERROR_VALUE
};
inline std::ostream& operator<<(std::ostream& os, Error err)
{
int errVal = static_cast<int>(err);
switch (err)
{
#ifndef PRODUCTION_BUILD // Don't print out names in production builds
#define ERROR_VALUE(NAME,VALUE,DESCR) case Error::NAME: return os << "[" #VALUE "]" #NAME <<"; " << DESCR;
ERROR_VALUES
#undef ERROR_VALUE
#endif
default:
return os <<errVal;
}
}
ERROR_VALUES
#undef ERROR_VALUE
#endif
default:
{
// If the error value isn't found (shouldn't happen)
return os << static_cast<int>(err);
break;
}
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
Error: [0]NO_ERROR; Everything is fine
Error: [1]FILE_NOT_FOUND; File is not found
Error: [2]LABEL_UNINITIALISED; A component tried to the label before it was initialised
Error: [-1]UKNOWN_ERROR; Uh oh
Run Code Online (Sandbox Code Playgroud)
这是个好办法,
enum Rank { ACE = 1, DEUCE, TREY, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING };
Run Code Online (Sandbox Code Playgroud)
用字符数组数组打印它
const char* rank_txt[] = {"Ace", "Deuce", "Trey", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Four", "King" } ;
Run Code Online (Sandbox Code Playgroud)
像这样
std::cout << rank_txt[m_rank - 1]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
143490 次 |
| 最近记录: |