C++字符串到枚举

发布于 2024-11-30 21:29:43 字数 274 浏览 4 评论 0原文

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

编辑:

感谢您的所有回复。我意识到对于我的具体情况有一种更简单的方法。字符串总是包含字符“S”,后跟一些数字,所以我只是这样做

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

,然后对 i 进行了切换。

Is there a simple way in C++ to convert a string to an enum (similar to Enum.Parse in C#)? A switch statement would be very long, so I was wondering if there is a simpler way to do this?

EDIT:

Thanks for all of your replies. I realized that there was a much simpler way to do it for my particular case. The strings always contained the charater 'S' followed by some number so i just did

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

and then did a switch on i.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

思念满溢 2024-12-07 21:29:43

std::map (或 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() }

A std::map<std::string, MyEnum> (or unordered_map) could do it easily. Populating the map would be just as tedious as the switch statement though.

Edit: Since C++11, populating is trivial:

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() }
迷雾森÷林ヴ 2024-12-07 21:29:43

使用 std::map 并使用 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);

Use std::map<std::string, Enum> and use boost::map_list_of to easily initialize it.

Example,

enum X
{
   A,
   B,
   C
};

std::map<std::string, X> xmap = boost::map_list_of("A", A)("B", B)("C",C);
吃→可爱长大的 2024-12-07 21:29:43

在某处看到这个例子

#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(){}
};

saw this example somewhere

#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(){}
};
埋情葬爱 2024-12-07 21:29:43

这对我有用:

enum NODES { Cone = 1, BaseColor = 2, NONE = 0 };

std::map<std::string, NODES> nodeMap;
nodeMap["Cone"] = NODES::Cone;
nodeMap["BaseColor"] = NODES::BaseColor;

this worked for me:

enum NODES { Cone = 1, BaseColor = 2, NONE = 0 };

std::map<std::string, NODES> nodeMap;
nodeMap["Cone"] = NODES::Cone;
nodeMap["BaseColor"] = NODES::BaseColor;
肥爪爪 2024-12-07 21:29:43

我用的是这个“绝招”> 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 ) );

I use this "trick" > http://codeproject.com/Articles/42035/Enum-to-String-and-Vice-Versa-in-C

After

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

insert

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

It works fine, if the values in the enum are not duplicates.

Example in code

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

vice versa

assert( EnumString< FORM >::To( f, str ) );
静谧幽蓝 2024-12-07 21:29:43

没有“内置方法”,但是有一些方法可以通过将值-名称对存储在数组中来实现此目的

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);

There is no "built-in way", but there are ways to achieve this by storing the pair value-name in an array

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);
何以心动 2024-12-07 21:29:43

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

In short: there is none. In C++ enums are static values and not objects like in C#. I suggest you use a function with some if else statements.

累赘 2024-12-07 21:29:43

这是不可能的,因为名称在运行时不可用。在编译期间,每个枚举都会替换为相应的整数值。

It is not possible because the names are not available at runtime. During compilation each enum is replaced with the corresponding integer value.

最佳男配角 2024-12-07 21:29:43

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

看看这个问题:Easy way to use enum types as string in C?

While there is no direct solution, there are a few possible workarounds.

Take a look at this question: Easy way to use variables of enum types as string in C?

素年丶 2024-12-07 21:29:43

您可以使用宏来尽量减少重复。这是技巧: 枚举、宏、Unicode 和标记粘贴

You can use macro to minimize repeating yourself. Here is the trick: Enums, Macros, Unicode and Token-Pasting

剩余の解释 2024-12-07 21:29:43

不,您必须使用 if/then 构造,或者使用映射或哈希表或某种其他类型的关联数据结构来促进这一点。

No, you'll have to use an if/then construction, or use a map or hash table or some other type of associative data structure to facilitate this.

蝶…霜飞 2024-12-07 21:29:43

“附加问题:是否可以处理未定义的字符串?我的意思是,如果我尝试获取responseHeaderMap[“cookie”]的值,该值是什么?(假设“cookie”未在responseHeaderMap中定义) – bart 2016 年 11 月 22 日 12:04"

好吧,您可以在之前进行检查:

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

在“cookie”存在检查之后,您可以通过使用获取它的值:

responseHeaderMap["cookie"]

希望有帮助

"Additional question: Is it possibile to handle undefined strings ? I mean if I try to get the value for responseHeaderMap["cookie"], what will be the value? (provided that "cookie" is not defined in the responseHeaderMap – bart s Nov 22 '16 at 12:04"

well, you can just make check before:

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

After "cookie" exist check, you can get it value with use:

responseHeaderMap["cookie"]

hope this help

來不及說愛妳 2024-12-07 21:29:43

您必须将字符串值(字符链)映射到相应的枚举值(整数)。以下是您在实践中使用 std::map 执行此操作的方法:

Demo

#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_encoding\n");
                break;
            case myenum::content_length:
                printf("String was content_length\n");
                break;
            case myenum::transfer_encoding:
                printf("String was transfer_encoding\n");
                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 映射来提示编译器该映射根本不应该被更改。异常处理是一个必要的邪恶,因为对于 const 映射,我们只能使用 .at() 方法,因为如果在映射中找不到键,它不会插入项目。在我看来,CWG 的决定有点不幸,因为这绝对不是什么“例外”,我们不应该支付费用(至少在这种情况下)。
  • 在 C++23 中,我们得到的 flat_map 更适合这种情况,因为我认为它将包含 constexpr 初始值设定项和赋值,这将允许我们在编译时布置整个映射,这样我们只需支付复制的开销将最终地图粘贴到 RAM 中。它对缓存也更加友好。

You will have to map the string values (chain of characters) to a corresponding enum value (integer). Here's how you would do this in practice using std::map:

Demo

#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_encoding\n");
                break;
            case myenum::content_length:
                printf("String was content_length\n");
                break;
            case myenum::transfer_encoding:
                printf("String was transfer_encoding\n");
                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");
}

Output:

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

A few notes:

  • We use a const map to hint to the compiler that this map isn't supposed to be changed at all. The exception handling is a necessary evil as for const maps we can only use the .at() method as it doesn't insert items if it doesn't find the key in the map. It's a bit of an unfortunate decision by the CWG in my view, as this is definitely nothing "exceptional" and we shouldn't have to pay the cost (in this case at least).
  • In C++23 we get flat_map which is more suitable in this case, as I suppose it will contain constexpr initializers and assignement which would allow us to lay out the whole map at compile time, so that we just pay the overhead of copy-pasting the final map to RAM. It's also a lot more cache-friendly.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文