Convert String -> Enum



  • Hallo,

    ich habe ein enum definiert:

    enum MyEnum{FAIL = 0, MISS = 1, SUCCESS = 2};
    

    So nun bekomme ich einen string und möchte aus dem einen Enum Value machen:

    f(std::string value)
    {
        //mache aus value einen MyEnum Wert, aber wie?
    }
    

    Andersherum möchte ich danach aus meinem Enum Wert einen integer Wert machen:

    f2(MyEnum value)
    {
        int i = (int) value; //darf ich das so, oder ist das Fehleranfällig?
    }
    


  • enum -> int ist garantiert und funktioniert, genauso übrigens wie int -> enum, solange der int-Wert zwischen dem höchsten und niedrigsten Wert des Enums liegt.
    Bei string -> enum ist es ein bisschen komplizierter. Steht in dem String "1" oder "MISS"? Wenn die Zahl drin steht, kannst du einfach string -> int -> enum machen, steht der Name drin, brauchst du eine Symboltabelle, weil die Namen sonst nicht im Kompilat existieren.



  • Enum Converter schrieb:

    f(std::string value)
    {
        //mache aus value einen MyEnum Wert, aber wie?
    }
    

    Wenn in value bloss der Wert steht, dann nach int Konvertieren.

    Enum Converter schrieb:

    f2(MyEnum value)
    {
        int i = (int) value; //darf ich das so, oder ist das Fehleranfällig?
    }
    

    Erlaubt.

    MfG, EOutOfResources

    EDIT: Schon wieder zu langsam...



  • ipsec schrieb:

    enum -> int ist garantiert und funktioniert, genauso übrigens wie int -> enum, solange der int-Wert zwischen dem höchsten und niedrigsten Wert des Enums liegt.

    Nicht ganz. Der Wertebereich liegt zwischen 0 und der nächst grösseren Zweierpotenz minus 1, falls die Enumeratoren nur positive Werte haben.

    Fall auch negative Werte vorkommen ist die untere Grenze der negative Wert der nächst grösseren Zweierpotenz.

    Für obiges Beispiel wäre also das zulässige Intervall [0,3].

    Oft wählt man den Wert der Enumeratoren ja absichtlich so, dass nur ein Bit gesetzt ist (also eine Zweierpotenz) um sie eindeutig verodern zu können:

    enum VALUES { A=1, B=2, C=4, D=8};  // Wertebereich [0,15]
    VALUES wasauchimmer = B|C|D;
    


  • Hm so stand das auch im Stroustrup, ich meinte allerdings auch mal irgendwo gelesen zu haben, dass der Standard nur den Wertebereich von MinWert bis MaxWert garantiert und ich dachte Stroustrup verlässt sich hier einfach auf die Garantien des Binärsystems, das ja 100% aller Implementierungen verwenden.
    Das mit dem Verodern macht aber Sinn, daran habe ich damals gar nicht gedacht.



  • Ich muss gestehen, dass meine Aussage ebenfalls auf dem Struppi basiert. Muss ich mal im Standard nachlesen.

    Aus dem working draft 02/2011 (N3242):

    7.2.7
    For an enumeration whose underlying type is fixed, the values of the enumeration are the values of the
    underlying type. Otherwise, for an enumeration where emin is the smallest enumerator and emax is the
    largest, the values of the enumeration are the values in the range bmin to bmax, defined as follows: Let K
    be 1 for a two’s complement representation and 0 for a one’s complement or sign-magnitude representation.
    bmax is the smallest value greater than or equal to max(|emin| - K, |emax|) and equal to 2^M - 1, where
    M is a non-negative integer. bmin is zero if emin is non-negative and -(bmax + K) otherwise. The size of
    the smallest bit-field large enough to hold all the values of the enumeration type is max(M, 1) if bmin is
    zero and M + 1 otherwise. It is possible to define an enumeration that has values not defined by any of its
    enumerators. If the enumerator-list is empty, the values of the enumeration are as if the enumeration had a
    single enumerator with value 0.
    


  • Ich habe z.B "MISS" als string Wert. Also lege ich einfach mal eine Symboltabelle an. Ich habe gehofft da komme ich drum herum.

    Ich würde das jetzt mit "map<string, MyEnum>" machen, ist das so gedacht?



  • Genau. Mit ein bisschen Makromagie kann man auch Enumeration und Symboltabelle gleichzeitig definieren.

    @inter2k: viele Dank, gut, dass das mal geklärt ist. Hätte man aber m.E. auch ein bisschen einfacher im Standard formulieren können...



  • Wie meinst du "Makromagie"? Ich bemerke nämlich gerade, dass das ganze ganz schön umständlich ist. Mein Enum hat 10 Einträge...

    Ich habe versucht eine statische map anzulegen, weiß aber nicht, wie ich die dann beschreiben soll...



  • Dazu gab es hier mal eine längere Diskussion (zwar eigentlich um Enum -> Name, aber das kannst du sicher leicht umbauen): http://www.c-plusplus.net/forum/267340



  • Also bei 10 Einträgen ist das nun wirklich nicht umständlich.

    class MyClass
    {
        enum MyEnum
        {
            FAIL = 0, MISS = 1, SUCCESS = 2
        };
        static std::map<std::string, MyEnum> mymap;
        static std::map<std::string, MyEnum> InitMyMap();
    };
    
    std::map<std::string, MyClass::MyEnum> MyClass::mymap = MyClass::InitMyMap();
    std::map<std::string, MyClass::MyEnum> MyClass::InitMyMap()
    {
        std::map<std::string, MyClass::MyEnum> m;
        m["FAIL"] = FAIL;
        m["MISS"] = MISS;
        m["SUCCESS"] = SUCCESS;
        return m;
    }
    

    Bei 1000 Einträgen würde ich mir dann vielleicht eine Lösung mit Makros überlegen.
    Man könnte sich noch was performateres überlegen, aber da sowas wohl i.d.R. im Zusammenhang mit irgendwelchen Benutzereingaben kommt ist die Performance wahrscheinlich eh wurscht.



  • Du kannst auch einen Code Generator nehmen: http://www.th-thielemann.de/tools/cpp-enum-to-string.html


Log in to reply