c++字符串到enum

C++ string to enum

本文关键字:enum 字符串 c++      更新时间:2023-10-16

在c++中是否有一种简单的方法将字符串转换为enum(类似于c#中的Enum.Parse)?一个switch语句将是非常长,所以我想知道是否有一个更简单的方法来做到这一点?

编辑:

谢谢你所有的回复。我意识到有一种更简单的方法来处理我的特殊情况。字符串总是包含字符'S'后面跟着一些数字,所以我只是做了

int i = atoi(myStr.c_str() + 1);

然后打开i

std::map<std::string, MyEnum>(或unordered_map)很容易做到这一点。不过,填充映射和switch语句一样乏味。

编辑:从c++ 11开始,填充是微不足道的:

static std::unordered_map<std::string,E> const table = { {"a",E::a}, {"b",E::b} };
auto it = table.find(str);
if (it != table.end()) {
  return it->second;
} else { error() }

使用std::map<std::string, Enum>boost::map_list_of可以轻松地初始化

,

enum X
{
   A,
   B,
   C
};
std::map<std::string, X> xmap = boost::map_list_of("A", A)("B", B)("C",C);

在某个地方见过这个例子

#include <map>
#include <string>
enum responseHeaders
{
    CONTENT_ENCODING,
    CONTENT_LENGTH,
    TRANSFER_ENCODING,
};
// String switch paridgam   
struct responseHeaderMap : public std::map<std::string, responseHeaders>
{
    responseHeaderMap()
    {
        this->operator[]("content-encoding") =  CONTENT_ENCODING;
        this->operator[]("content-length") = CONTENT_LENGTH;
        this->operator[]("transfer-encoding") = TRANSFER_ENCODING;
    };
    ~responseHeaderMap(){}
};

我使用了这个"技巧";比;http://codeproject.com/Articles/42035/Enum-to-String-and-Vice-Versa-in-C

enum FORM {
    F_NONE = 0,
    F_BOX,
    F_CUBE,
    F_SPHERE,
};

插入
Begin_Enum_String( FORM )
{
    Enum_String( F_NONE );
    Enum_String( F_BOX );
    Enum_String( F_CUBE );
    Enum_String( F_SPHERE );
}
End_Enum_String;

如果枚举中的值不重复,则正常工作。

代码示例

enum FORM f = ...
const std::string& str = EnumString< FORM >::From( f );

亦然

assert( EnumString< FORM >::To( f, str ) );

没有"内置的方法",但是可以通过在数组

中存储对value-name来实现这一点。
enum myEnum
{
    enumItem0,
    enumItem1,
    enumItem7 = 7,
    enumItem8
};
std::vector<std::pair<myEnum,std::string>>   gMap;
#define ADDITEM(x)  gMap.push_back(std::pair<myEnum,std::string>(x,#x));

ADDITEM(enumItem0);
ADDITEM(enumItem1);
ADDITEM(enumItem7);
ADDITEM(enumItem8);

这对我有用:

enum NODES { Cone = 1, BaseColor = 2, NONE = 0 };
std::map<std::string, NODES> nodeMap;
nodeMap["Cone"] = NODES::Cone;
nodeMap["BaseColor"] = NODES::BaseColor;

简而言之:没有。在c++中,枚举是静态值,而不是c#中的对象。我建议您使用一些if else语句的函数

这是不可能的,因为这些名称在运行时不可用。在编译过程中,每个枚举被替换为相应的整数值。

虽然没有直接的解决方案,但有一些可能的变通方法。

看一下这个问题:在C中使用枚举类型的变量作为字符串的简单方法?

你可以使用宏来减少重复。这里是技巧:枚举,宏,Unicode和标记粘贴

不,您必须使用if/then结构,或使用映射或哈希表或其他类型的关联数据结构来实现这一点

"附加问题:是否有可能处理未定义的字符串?我的意思是,如果我试图获得responseHeaderMap["cookie"]的值,将是什么值?(前提是"cookie"没有在responseHeaderMap中定义- bart ' s Nov 22 '16 at 12:04"

好吧,你可以先检查一下:

auto it = responseHeaderMap.find("cookie");
if (it != responseHeaderMap.end())
{
     // "cookie" exist, can take value 
}

在"cookie"存在检查后,您可以使用:

responseHeaderMap["cookie"]

希望对您有所帮助

您必须将字符串值(字符链)映射到相应的枚举值(整数)。下面是如何在实践中使用std::map:

演示
#include <cstdio>
#include <map>
#include <string_view>
#include <stdexcept>
enum class myenum
{
    content_encoding,
    content_length,
    transfer_encoding,
};
// In C++23 use a constexpr flat_map instead
const std::map<std::string_view, myenum> map_myenum = {
    {"content-encoding", myenum::content_encoding},
    {"content-length", myenum::content_length},
    {"transfer-encoding", myenum::transfer_encoding},
};
auto test(std::string_view str)
{
    try {
        switch(map_myenum.at(str)) {
            case myenum::content_encoding:
                printf("String was content_encodingn");
                break;
            case myenum::content_length:
                printf("String was content_lengthn");
                break;
            case myenum::transfer_encoding:
                printf("String was transfer_encodingn");
                break;
        }
    } catch(const std::out_of_range& e) {
        printf("String didn't match any criteria!n");
    }
    
}
int main()
{
    test("content-encoding");
    test("content-length");
    test("some random other stuff");
}
输出:

String was content_encoding
String was content_length
String didn't match any criteria!

注意事项:

    我们使用const map来暗示编译器这个map根本不应该被修改。异常处理是必要的,因为对于const映射,我们只能使用.at()方法,因为如果它在映射中找不到键,它就不会插入项。在我看来,这是CWG的一个不幸的决定,因为这绝对没有什么"特别"的。我们不应该支付成本(至少在这种情况下)。在c++ 23中,我们得到flat_map,这在这种情况下更合适,因为我认为它将包含constexpr初始化器和赋值,这将允许我们在编译时布局整个映射,因此我们只需支付将最终映射复制粘贴到RAM的开销。它也更加缓存友好。