簡體   English   中英

在 C++ 中枚舉的字符串

[英]String to enum in C++

有沒有辦法將文本文件中的字符串與枚舉值相關聯?

問題是:我有一些枚舉值作為字符串存儲在一個文本文件中,我在滿足某些條件時即時讀取這些值......現在我想將讀取值分配給一個枚舉。

這樣做的最有效方法是什么? 它不需要是最簡單的方法。

您可以設置一個可以反復使用的地圖:

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");
}
std::map< string, enumType> enumResolver;

接受的答案不包含完整列表。 我正在添加我從接受的答案中創建的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;
    }
};

用法很簡單:

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

采用:

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

我同意std::map是最簡單的解決方案的許多答案。

如果您需要更快的速度,可以使用哈希映射。 也許您的編譯器已經提供了一個,例如hash_map或即將推出的標准 unordered_map,或者您可以從boost獲得一個。 當提前知道所有字符串時,也可以使用完美散列

看看Boost.Bimap ,它提供了兩組值之間的雙向關聯。 您還可以選擇底層容器。

這是你想要的嗎? 初始化是直接的,不需要實例化。

用法:

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

圖書館:

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[]

使用std::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";
    }
}

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

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

從這里使用 C++ 反射庫: https : //github.com/tapika/cppreflect

您可以 - 包括這樣的庫:

#include "cppreflect/cppreflect.h"

基本用法:

聲明枚舉:

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

    myenum_enumValue1,
    myenum_enumValue2,
    myenum_enumValue3 = 5,

    // comment
    myenum_enumValue4
);

轉換邏輯:

從枚舉到字符串:

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

=> "enumValue3"

從字符串到枚舉:

enumName value;

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

=> 

value == myenum_enumValue4

主要/核心功能位於此處:

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

自己解析字符串,將字符串與值匹配(這也是map<string, enum>的索引。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM