我如何ToString()在c + +的枚舉?在Java和C#中,我只會調用ToString。我如何ToString()在c + +的枚舉?
enum Colours
{
Red =0,
Green=1,
Blue=2
};
我需要創建一個字符串:「Invalid color'」+ color +「'selected。」
我如何ToString()在c + +的枚舉?在Java和C#中,我只會調用ToString。我如何ToString()在c + +的枚舉?
enum Colours
{
Red =0,
Green=1,
Blue=2
};
我需要創建一個字符串:「Invalid color'」+ color +「'selected。」
雖然這通常是通過交換機做,我更喜歡的數組:
#include <iostream>
namespace foo {
enum Colors { BLUE = 0, RED, GREEN, SIZE_OF_ENUM };
static const char* ColorNames[] = { "blue", "red", "green" };
// statically check that the size of ColorNames fits the number of Colors
static_assert(sizeof(foo::ColorNames)/sizeof(char*) == foo::SIZE_OF_ENUM
, "sizes dont match");
} // foo
int main()
{
std::cout << foo::ColorNames[foo::BLUE] << std::endl;
return 0;
}
顯式數組的大小具有生成編譯時 錯誤的利益應在枚舉變化的大小和你忘了加 適當的字符串。
或者,Boost Vault中有Boost.Enum。圖書館 尚未正式發佈,但相當穩定,並提供你想要的 。我不會推薦給新手。
這本質上是不可能的。
C++ enum只是一組帶編譯時名稱的數字。
在運行時,它們與普通數字無法區分。
您需要編寫一個返回字符串的switch
語句。
它是如何工作在C#....反射? – CodingHero 2012-02-05 15:49:15
@CodingQuant:是的。您可以在「Enum」類的源代碼中看到反射。 – SLaks 2012-02-05 19:12:05
您可以將這些名稱存儲在一個字符串數組中,其索引值爲enum
值。
enum Colours
{
Red =0,
Green=1,
Blue=2
};
char* names[3] = {"Red", "Green", "Blue"};
然後你就可以打印:"Invalid colour '" + names[colour] + "' selected."
但是,如果你不按順序定義enum
值這種方法可能不是非常有用的。在這種情況下,這種方法會浪費記憶。正如亞歷山大•蓋斯勒(Alexander Gessler)所提到的那樣,在enum
的值上寫一個switch
的函數將會很有用。另一種選擇可能是來自STL的map
。
你必須做手工,即
const char* ToString(Colours co) {
switch(co) {
case Red:
return "Red";
// ...
}
}
查找表也將是可能的。我還看到有人使用自定義腳本在源代碼之上生成這些東西。
enum Color
{
Red =0,
Green=1,
Blue=2
};
std::string ColorMap[] = { "Red", "Green","Blue" };
使用ColorMap[c]
得到字符串表示:
std::string msg = "Invalid colour '" + ColorMap[c] + "' selected.";
然而,如果枚舉值是不連續的,那麼你可以使用std::map
而不是爲:
enum Color
{
Red = 0x1,
Green = 0x2,
Blue = 0x4,
Black = 0x8,
};
//C++11 only, as it uses std::initializer_list
std::map<Color, std::string> ColorMap = {
{Red, "Red"},
{Green, "Green"},
{Blue, "Blue"},
{Black, "Black"}
};
//same as before!
std::string msg = "Invalid colour '" + ColorMap[c] + "' selected.";
在我看來,最好的解決方案,因爲這種方法也可以用於包含空白的枚舉。例如。紅色= 0x01,綠色,藍色= 0x10,黃色。 – Anonymous 2014-06-19 08:17:48
As @FlopCoder says:
enum Colours
{
Red =0,
Green=1,
Blue=2
};
char* ColourNames[] = { "Red", "Green", "Blue" };
int colour = Green;
printf("Invalid colour '%s' selected.", ColourNames[ colour ]);
這當然只適用於你的枚舉從0開始並且是連續的。
@ Nawaz的方式是更多雖然C++時尚。
如何一點點魔法與宏:
#include <iostream>
#include <string>
#include <vector>
// http://stackoverflow.com/questions/236129/how-to-split-a-string-in-c
std::vector<std::string> split(const std::string &text, char sep) {
std::vector<std::string> tokens;
int start = 0, end = 0;
while ((end = text.find(sep, start)) != std::string::npos) {
tokens.push_back(text.substr(start, end - start));
start = end + 1;
}
tokens.push_back(text.substr(start));
return tokens;
}
#define ENUM(name, ...)\
enum name \
{\
__VA_ARGS__\
};\
std::vector<std::string> name##Map = split(#__VA_ARGS__, ',');\
std::string toString(const name v) { return name##Map.at(v);}
ENUM(Color, Red,Green,Blue)
int main(int c, char**v)
{
std::cout << toString(Red) << toString(Blue);
return 0;//a.exec();
}
是的,我明白,這是醜陋的,你最好不要做做這種事情
醜陋?這是太棒了! – 2012-03-14 11:40:45
我很確定這可以通過C++ 11參數包更乾淨地完成 - 所以在運行時根本不會有任何工作。 – einpoklum 2016-02-04 15:41:03
我真的很喜歡的宏觀方法@ Lol4t0 。
我伸出它能夠枚舉從字符串太轉換:
#include <iostream>
#include <string>
#include <vector>
// http://stackoverflow.com/questions/236129/how-to-split-a-string-in-c
std::vector<std::string> split(const std::string &text, char sep) {
std::vector<std::string> tokens;
int start = 0, end = 0;
while ((end = text.find(sep, start)) != std::string::npos) {
tokens.push_back(text.substr(start, end - start));
start = end + 1;
}
tokens.push_back(text.substr(start));
return tokens;
}
#define ENUM(name, ...)\
enum name\
{\
__VA_ARGS__\
};\
static const int name##Size = (sizeof((int[]){__VA_ARGS__})/sizeof(int));\
static const vector<string> name##ToStringMap = split(#__VA_ARGS__, ',');\
const string name##ToString(const name value)\
{\
return name##ToStringMap.at(value);\
};\
map<string, name> name##ToFromStringMap(...)\
{\
map<string, name> m;\
name args[name##Size] = { __VA_ARGS__ };\
\
int i;\
for(i = 0; i < name##Size; ++i)\
{\
m[name##ToString(args[i])] = args[i];\
}\
return m;\
};\
static map<string, name> name##FromStringMap = name##ToFromStringMap(__VA_ARGS__);\
const name name##FromString(const string value, const name defaultValue)\
{\
if(name##FromStringMap.count(value) == 0)\
{\
return defaultValue;\
}\
return name##FromStringMap[value];\
};
用法:
ENUM(MyEnum, Value1, Value2)
void main()
{
string valueName = MyEnumToString(MyEnum::Value2);
MyEnum value = MyEnumFromString(valueName, MyEnum::Value1);
}
我不是一個C++專家,所以讓我知道你在想什麼或如何做得更好。
如果您忘記*添加字符串,它不會生成錯誤... – 2012-02-05 18:29:02
@MatthieuM。真正。構建這樣的東西的唯一可靠方法可能是宏。 – pmr 2012-02-05 18:37:13
我很害怕。我一直認爲這也是一種恥辱,我會讚賞編譯器構建函數的一面。我發現的一種方法是使用宏,儘管這或多或少地將函數內聯。另一個是使用測試來確保翻譯適用於以前的類型(至少),然後依靠開發人員*思考* :) – 2012-02-05 19:55:29