在 C++ 中枚举的字符串

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/726664/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 16:57:12  来源:igfitidea点击:

String to enum in C++

c++stringenums

提问by Shree

Is there a way to associate a string from a text file with an enum value?

有没有办法将文本文件中的字符串与枚举值相关联?

The problem is: I have a few enum values stored as string in a text file which I read on the fly on meeting some condition... Now I want to assign the read value to an enum.

问题是:我有一些枚举值作为字符串存储在一个文本文件中,我在满足某些条件时即时读取这些值......现在我想将读取值分配给一个枚举。

What is the most effective way to do so? It doesn't need to be the simplest approach.

这样做的最有效方法是什么?它不需要是最简单的方法。

回答by Eclipse

You can set up a map that you can use over and over:

您可以设置一个可以反复使用的地图:

template <typename T>
class EnumParser
{
    map <string, T> enumMap;
public:
    EnumParser(){};

    T ParseSomeEnum(const string &value)
    { 
        map <string, T>::const_iterator iValue = enumMap.find(value);
        if (iValue  == enumMap.end())
            throw runtime_error("");
        return iValue->second;
    }
};

enum SomeEnum
{
    Value1,
    Value2
};
EnumParser<SomeEnum>::EnumParser()
{
    enumMap["Value1"] = Value1;
    enumMap["Value2"] = Value2;
}

enum OtherEnum
{
    Value3, 
    Value4
};
EnumParser<OtherEnum>::EnumParser()
{
    enumMap["Value3"] = Value3;
    enumMap["Value4"] = Value4;
}

int main()
{
    EnumParser<SomeEnum> parser;
    cout << parser.ParseSomeEnum("Value2");
}

回答by tpdi

std::map< string, enumType> enumResolver;

回答by Mark Ransom

I agree with many of the answers that std::mapis the easiest solution.

我同意许多答案,这std::map是最简单的解决方案。

If you need something faster, you can use a hash map. Perhaps your compiler already offers one, such as hash_mapor the upcoming standard unordered_map, or you can get one from boost. When all the strings are known ahead of time, perfect hashingcan be used as well.

如果您需要更快的速度,可以使用哈希映射。也许您的编译器已经提供了一个,例如hash_map或即将推出的标准 unordered_map,或者您可以从boost获得一个。当提前知道所有字符串时,也可以使用完美散列

回答by javapowered

Accepted answer doesn't contain full listing. I'm adding EnumParser.hwhich I created from the accepted answer, hope it can help

接受的答案不包含完整列表。我正在添加EnumParser.h我从接受的答案中创建的内容,希望它能有所帮助

#include <string>
#include <map>

using namespace std;

template <typename T> class EnumParser
{
    map<string, T> enumMap;
public:
    EnumParser(){};

    T ParseSomeEnum(const string &value)
    { 
        typename map <string, T>::const_iterator iValue = enumMap.find(value);
        if (iValue  == enumMap.end())
            throw runtime_error("");
        return iValue->second;
    }
};

Usage is simple:

用法很简单:

enum FieldType
{
    Char,
    Integer,
    Long,
    Fixed,
    Price,
    Date,
    Time
};

EnumParser<FieldType>::EnumParser()
{
    enumMap["Char"] = Char;
    enumMap["Integer"] = Integer;
    enumMap["Long"] = Long;
    enumMap["Fixed"] = Fixed;
    enumMap["Price"] = Price;
    enumMap["Date"] = Date;
    enumMap["Time"] = Time;
}

use:

用:

 EnumParser<FieldType> fieldTypeParser;
 FieldType val = fieldTypeParser.ParseSomeEnum(stringValue)

回答by Vadim Ferderer

Look at Boost.Bimap, it provides bidirectional associations between two sets of values. You can also choose the underlying container.

看看Boost.Bimap,它提供了两组值之间的双向关联。您还可以选择底层容器。

回答by Ben Lai

Is this what you want? The initialization is straight, and no instantiation is needed.

这是你想要的吗?初始化是直接的,不需要实例化。

usage:

用法:

enum SomeEnum
{
    ENUM_ONE,
    ENUM_TWO,
    ENUM_THREE,
    ENUM_NULL
};

DEFINE_PAIRLIST(CEnumMap, SomeEnum)

INIT_PAIRLIST(CEnumMap)=
{
        {"One", ENUM_ONE},
        {"Two", ENUM_TWO},
        {"Three", ENUM_THREE},
        {"", ENUM_NULL}
};

main{
    // Get enum from string
    SomeEnum i = CEnumMap::findValue("One");

    // Get string from enum
    SomeEnum eee = ENUM_ONE;
    const char* pstr = CEnumMap::findKey(eee);
    ...
}

library:

图书馆:

template <class T>
struct CStringPair
{
    const char* _name;
    T _value;
};

template <class T, class Derived>
struct CStringPairHandle
{
    typedef CStringPair<T> CPair;
    static const CStringPair<T> * getPairList(){
        return Derived::implementation();
    }
    static T findValue(const char* name){
        const CStringPair<T> * p = getPairList();
        for (; p->_name[0]!=0; p++)
            if (strcmp(name,p->_name)==0)
                break;
        return p->_value;
    }

    static const char* findKey(T value){
        const CStringPair<T> * p = getPairList();
        for (; p->_name[0]!=0; p++)
            if (strcmp(value,p->_value)==0)
                break;
        return p->_name;
    };
};

#define DEFINE_PAIRLIST(name, type) struct name:public CStringPairHandle<type, name>{ \
    static CPair _pairList[];       \
    static CPair* implementation(){     \
        return _pairList;           \
    }};
#define INIT_PAIRLIST(name) name::CPair name::_pairList[]

回答by Ben Lai

Using a std::mapraises the question: how does the map get initialised? I would rather use a function:

使用 astd::map提出了一个问题:地图如何初始化?我宁愿使用一个函数:

enum E { A, B };

E f( const std::string & s ) {
   if ( s == "A" ) {
      return A;
    }
    else if ( s == "B" ) {
      return B;
    }
    else {
      throw "Your exception here";
    }
}

回答by dirkgently

Parse the string yourself, match the string with a value (which is also an index to a map<string, enum>.

自己解析字符串,将字符串与一个值(它也是map<string, enum>.

回答by user1095108

You can calculate the hash of the string and then use this:

您可以计算字符串的哈希值,然后使用它:

template <typename H, typename E>
E map_hash(H const key, std::initializer_list<std::pair<H, E>> const il)
{
  auto const i(
    std::find_if(il.begin(),
      il.end(),
      [key](auto& p)
      {
        return p.first == key;
      }
    )
  );

  assert(i != il.end());

  return i->second;
}

回答by TarmoPikaro

Using C++ reflection library from here: https://github.com/tapika/cppreflect

从这里使用 C++ 反射库:https: //github.com/tapika/cppreflect

You can - include library like this:

您可以 - 包括这样的库:

#include "cppreflect/cppreflect.h"

Basic usage:

基本用法:

Declare enumeration:

声明枚举:

DECLARE_ENUM( enumName,
    // Prefix for all enums, "" if no prefix used.
    "myenum_",

    myenum_enumValue1,
    myenum_enumValue2,
    myenum_enumValue3 = 5,

    // comment
    myenum_enumValue4
);

Conversion logic:

转换逻辑:

From enumeration to string:

从枚举到字符串:

printf( EnumToString(myenum_enumValue3).c_str() );

=> "enumValue3"

From string to enumeration:

从字符串到枚举:

enumName value;

if( !StringToEnum("enumValue4", value) )
    printf("Conversion failed...");

=> 

value == myenum_enumValue4

Main / core functionality resides in here:

主要/核心功能位于此处:

https://github.com/tapika/cppreflect/blob/master/cppreflect/enumreflect.h

https://github.com/tapika/cppreflect/blob/master/cppreflect/enumreflect.h