Wie konvertiert man eine Variable vom Typ Enum in einen String?

Lesezeit: 1 Minute

Wie konvertiert man eine Variable vom Typ Enum in einen
Psihodelie

Wie kann man printf dazu bringen, die Werte von Variablen anzuzeigen, die vom Typ Enum sind? Zum Beispiel:

typedef enum {Linux, Apple, Windows} OS_type; 
OS_type myOS = Linux;

und was ich brauche ist so etwas wie

printenum(OS_type, "My OS is %s", myOS);

die eine Zeichenfolge “Linux” zeigen muss, keine Ganzzahl.

Ich nehme an, zuerst muss ich ein wertindiziertes Array von Zeichenfolgen erstellen. Aber ich weiß nicht, ob das die schönste Art ist, es zu tun. Ist es überhaupt möglich?

  • Treffen Sie Ihre Wahl: hier, hier, hier. Es ist ein Durcheinander, sie sind alle Halbduplikate.

    – rubenvb

    11. Februar 2014 um 10:25 Uhr

  • Ein anderer, dieser ist vollständiger.

    – bit2shift

    27. März 2016 um 0:21 Uhr


  • Mögliches Duplikat von stackoverflow.com/questions/207976/… für C++ und stackoverflow.com/questions/9907160/… für C

    – Ciro Santilli Путлер Капут 六四事

    11. Dezember 2016 um 15:01 Uhr

  • So viele Antworten, aber keine “Enumerationsklasse”

    – Vivic

    23. Juni 2017 um 13:21 Uhr

1646953810 562 Wie konvertiert man eine Variable vom Typ Enum in einen
Bo Persson

Es gibt wirklich keine schöne Art, dies zu tun. Richten Sie einfach ein Array von Zeichenfolgen ein, die von der Aufzählung indiziert werden.

Wenn Sie viel ausgeben, können Sie einen Operator<< definieren, der einen Aufzählungsparameter akzeptiert und die Suche für Sie übernimmt.

  • Sie können auch zur Kompilierzeit überprüfen, ob Ihr Array die erwartete Anzahl von Zeichenfolgen enthält.

    – markh44

    23. Februar 2011 um 18:06 Uhr

  • Ich weiß, dass ich damit in der großen Minderheit bin, aber für Programmierer wie mich, die sich nicht auf massive Bibliotheken von Drittanbietern und/oder Marco-durchsiebten Code verlassen möchten, um spracheigene Mängel zu beheben, finde ich das gut die mit Abstand einfachste und reinste Lösung für den heutigen Standard. +1

    – Syndog

    13. Februar 2014 um 14:31 Uhr


  • @Syndog Dann wird die 56 Aufzählungszeichen lange Aufzählung in Ihrem Produktionscode von diesem Programmierer unter großem Druck aktualisiert, eine überfällige Funktion freizugeben, und er vergisst, dieses Aufzählungs-indizierte Array zu aktualisieren. Es bleibt unbemerkt, da die zugehörige Druckfunktion nur vom Debugging-Code der Anwendung verwendet wird. 2 Monate später sind Sie der Erste, der diesen Debug-Code tatsächlich ausführt: Er gibt Ihnen dann die falschen Informationen, sodass Sie einen halben Tag damit verlieren, auf der Grundlage dieser falschen Informationen Annahmen zu treffen, bevor Sie feststellen, dass Sie zuerst den Debug-Code debuggen mussten: der Design beruht auf expliziter Vervielfältigung.

    – Anzeige N

    20. August 2015 um 8:34 Uhr


  • @AdN Dieses Design ist falsch. Die Zuordnung von Enum zu menschenlesbarem String sollte nicht als ein Array von Strings implementiert werden, die durch den Enum-Wert indiziert werden. Ihre Erfahrung zeigt (vermutlich) warum. Die Zuordnung sollte ein explizites Array von (enum,string)-Paaren sein, wenn Sie also vergessen, einen Eintrag für Ihren neuen enum-Wert hinzuzufügen, erhalten Sie “???” als Ausgabe, aber zumindest wird es nicht die Namen all Ihrer anderen Aufzählungen vermasseln.

    – Braubock

    15. Januar 2016 um 5:10 Uhr

  • @AdN In Ihrem Szenario bevorzuge ich eine Funktion, die einen Schalter (ohne Standardklausel) anstelle eines Arrays enthält, und setze die Compiler-Schalter in der Build-Datei so, dass ein Fehler für einen Schalter über eine Aufzählung ausgegeben wird, die nicht alle abdeckt mögliche Werte. Das Hinzufügen eines neuen Enum-Eintrags ohne Aktualisierung der relevanten Switch-Anweisungen führt zu einem Kompilierungsfehler.

    – Tauchfreak

    30. November 2016 um 17:36 Uhr

  • Dies ist die einzige Lösung, die funktioniert, wenn Ihre Aufzählung mehr als 256 Elemente enthält.

    – dshin

    25. April 2016 um 23:01 Uhr

  • Das ist schön und erschreckend zugleich. Entschuldigen Sie, während ich für ein paar Stunden unter der Dusche gehe.

    – Allourcode

    11. Juni 2021 um 6:13 Uhr

  • Nicht so schlimm wie … 😉 stackoverflow.com/questions/70455489/… am einfachsten könnte es sein, dieselben Elemente zweimal einzuschließen, aber dynamische Objekte vor der Verarbeitung in einem char * -Array zu speichern usw. Und Intellisense weint selbst ein bisschen …

    – Tom

    30. Dezember 2021 um 12:57 Uhr


Wie konvertiert man eine Variable vom Typ Enum in einen
Nawaz

Verwenden std::map<OS_type, std::string> und füllen Sie es mit enum als Schlüssel und Zeichenfolgendarstellung als Werte, dann können Sie Folgendes tun:

printf("My OS is %s", enumMap[myOS].c_str());
std::cout << enumMap[myOS] ;

  • sehr ineffizient, jedes Mal eine logN-Suche durchzuführen

    – Fabio

    13. November 2021 um 16:25 Uhr

Ich habe die Lösungen von James, Howard und Éder kombiniert und eine allgemeinere Implementierung erstellt:

  • Int-Wert und benutzerdefinierte Zeichenfolgendarstellung können optional für jedes Enum-Element definiert werden
  • “enum-Klasse” wird verwendet

Der vollständige Code ist unten geschrieben (verwenden Sie “DEFINE_ENUM_CLASS_WITH_ToString_METHOD” zum Definieren einer Aufzählung) (Online-Demo).

#include <boost/preprocessor.hpp>
#include <iostream>

// ADD_PARENTHESES_FOR_EACH_TUPLE_IN_SEQ implementation is taken from:
// http://lists.boost.org/boost-users/2012/09/76055.php
//
// This macro do the following:
// input:
//      (Element1, "Element 1 string repr", 2) (Element2) (Element3, "Element 3 string repr")
// output:
//      ((Element1, "Element 1 string repr", 2)) ((Element2)) ((Element3, "Element 3 string repr"))
#define HELPER1(...) ((__VA_ARGS__)) HELPER2
#define HELPER2(...) ((__VA_ARGS__)) HELPER1
#define HELPER1_END
#define HELPER2_END
#define ADD_PARENTHESES_FOR_EACH_TUPLE_IN_SEQ(sequence) BOOST_PP_CAT(HELPER1 sequence,_END)


// CREATE_ENUM_ELEMENT_IMPL works in the following way:
//  if (elementTuple.GetSize() == 4) {
//      GENERATE: elementTuple.GetElement(0) = elementTuple.GetElement(2)),
//  } else {
//      GENERATE: elementTuple.GetElement(0),
//  }
// Example 1:
//      CREATE_ENUM_ELEMENT_IMPL((Element1, "Element 1 string repr", 2, _))
//  generates:
//      Element1 = 2,
//
// Example 2:
//      CREATE_ENUM_ELEMENT_IMPL((Element2, _))
//  generates:
//      Element1,
#define CREATE_ENUM_ELEMENT_IMPL(elementTuple)                                          \
BOOST_PP_IF(BOOST_PP_EQUAL(BOOST_PP_TUPLE_SIZE(elementTuple), 4),                       \
    BOOST_PP_TUPLE_ELEM(0, elementTuple) = BOOST_PP_TUPLE_ELEM(2, elementTuple),        \
    BOOST_PP_TUPLE_ELEM(0, elementTuple)                                                \
),

// we have to add a dummy element at the end of a tuple in order to make 
// BOOST_PP_TUPLE_ELEM macro work in case an initial tuple has only one element.
// if we have a tuple (Element1), BOOST_PP_TUPLE_ELEM(2, (Element1)) macro won't compile.
// It requires that a tuple with only one element looked like (Element1,).
// Unfortunately I couldn't find a way to make this transformation, so
// I just use BOOST_PP_TUPLE_PUSH_BACK macro to add a dummy element at the end
// of a tuple, in this case the initial tuple will look like (Element1, _) what
// makes it compatible with BOOST_PP_TUPLE_ELEM macro
#define CREATE_ENUM_ELEMENT(r, data, elementTuple)                                      \
    CREATE_ENUM_ELEMENT_IMPL(BOOST_PP_TUPLE_PUSH_BACK(elementTuple, _))

#define DEFINE_CASE_HAVING_ONLY_ENUM_ELEMENT_NAME(enumName, element)                                        \
    case enumName::element : return BOOST_PP_STRINGIZE(element);
#define DEFINE_CASE_HAVING_STRING_REPRESENTATION_FOR_ENUM_ELEMENT(enumName, element, stringRepresentation)  \
    case enumName::element : return stringRepresentation;

// GENERATE_CASE_FOR_SWITCH macro generates case for switch operator.
// Algorithm of working is the following
//  if (elementTuple.GetSize() == 1) {
//      DEFINE_CASE_HAVING_ONLY_ENUM_ELEMENT_NAME(enumName, elementTuple.GetElement(0))
//  } else {
//      DEFINE_CASE_HAVING_STRING_REPRESENTATION_FOR_ENUM_ELEMENT(enumName, elementTuple.GetElement(0), elementTuple.GetElement(1))
//  }
//
// Example 1:
//      GENERATE_CASE_FOR_SWITCH(_, EnumName, (Element1, "Element 1 string repr", 2))
//  generates:
//      case EnumName::Element1 : return "Element 1 string repr";
//
// Example 2:
//      GENERATE_CASE_FOR_SWITCH(_, EnumName, (Element2))
//  generates:
//      case EnumName::Element2 : return "Element2";
#define GENERATE_CASE_FOR_SWITCH(r, enumName, elementTuple)                                                                                                 \
    BOOST_PP_IF(BOOST_PP_EQUAL(BOOST_PP_TUPLE_SIZE(elementTuple), 1),                                                                                       \
        DEFINE_CASE_HAVING_ONLY_ENUM_ELEMENT_NAME(enumName, BOOST_PP_TUPLE_ELEM(0, elementTuple)),                                                          \
        DEFINE_CASE_HAVING_STRING_REPRESENTATION_FOR_ENUM_ELEMENT(enumName, BOOST_PP_TUPLE_ELEM(0, elementTuple), BOOST_PP_TUPLE_ELEM(1, elementTuple))     \
    )


// DEFINE_ENUM_CLASS_WITH_ToString_METHOD final macro witch do the job
#define DEFINE_ENUM_CLASS_WITH_ToString_METHOD(enumName, enumElements)          \
enum class enumName {                                                           \
    BOOST_PP_SEQ_FOR_EACH(                                                      \
        CREATE_ENUM_ELEMENT,                                                    \
        0,                                                                      \
        ADD_PARENTHESES_FOR_EACH_TUPLE_IN_SEQ(enumElements)                     \
    )                                                                           \
};                                                                              \
inline const char* ToString(const enumName element) {                           \
        switch (element) {                                                      \
            BOOST_PP_SEQ_FOR_EACH(                                              \
                GENERATE_CASE_FOR_SWITCH,                                       \
                enumName,                                                       \
                ADD_PARENTHESES_FOR_EACH_TUPLE_IN_SEQ(enumElements)             \
            )                                                                   \
            default: return "[Unknown " BOOST_PP_STRINGIZE(enumName) "]";       \
        }                                                                       \
}

DEFINE_ENUM_CLASS_WITH_ToString_METHOD(Elements,
(Element1)
(Element2, "string representation for Element2 ")
(Element3, "Element3 string representation", 1000)
(Element4, "Element 4 string repr")
(Element5, "Element5", 1005)
(Element6, "Element6 ")
(Element7)
)
// Generates the following:
//      enum class Elements {
//          Element1, Element2, Element3 = 1000, Element4, Element5 = 1005, Element6,
//      };
//      inline const char* ToString(const Elements element) {
//          switch (element) {
//              case Elements::Element1: return "Element1";
//              case Elements::Element2: return "string representation for Element2 ";
//              case Elements::Element3: return "Element3 string representation";
//              case Elements::Element4: return "Element 4 string repr";
//              case Elements::Element5: return "Element5";
//              case Elements::Element6: return "Element6 ";
//              case Elements::Element7: return "Element7";
//              default: return "[Unknown " "Elements" "]";
//          }
//      }

int main() {
    std::cout << ToString(Elements::Element1) << std::endl;
    std::cout << ToString(Elements::Element2) << std::endl;
    std::cout << ToString(Elements::Element3) << std::endl;
    std::cout << ToString(Elements::Element4) << std::endl;
    std::cout << ToString(Elements::Element5) << std::endl;
    std::cout << ToString(Elements::Element6) << std::endl;
    std::cout << ToString(Elements::Element7) << std::endl;

    return 0;
}

  • sehr ineffizient, jedes Mal eine logN-Suche durchzuführen

    – Fabio

    13. November 2021 um 16:25 Uhr

1646953811 666 Wie konvertiert man eine Variable vom Typ Enum in einen
Andreas

Das Problem mit C-Enumerationen ist, dass es kein eigener Typ ist, wie es in C++ der Fall ist. Eine Aufzählung in C ist eine Möglichkeit, Bezeichner ganzzahligen Werten zuzuordnen. Nur das. Aus diesem Grund ist ein Enum-Wert mit ganzzahligen Werten austauschbar.

Wie Sie richtig erraten haben, besteht eine gute Möglichkeit darin, eine Zuordnung zwischen dem Aufzählungswert und einer Zeichenfolge zu erstellen. Zum Beispiel:

char * OS_type_label[] = {
    "Linux",
    "Apple",
    "Windows"
};

  • Ich bin – scheinbar fälschlicherweise – davon ausgegangen, dass die Programmiersprache auf C beschränkt ist.

    – Andreas

    23. Februar 2011 um 16:19 Uhr

  • Du bist etwas abseits, enum sind Typen in C. Ganzzahlige Enumerationstypkonstanten sind vom Typ int und nicht von der enum Art, durch die sie definiert sind, ist vielleicht das, was Sie sagen wollten. Aber ich verstehe überhaupt nicht, was das mit der Frage zu tun hat.

    – Jens Gustedt

    23. Februar 2011 um 17:57 Uhr

989230cookie-checkWie konvertiert man eine Variable vom Typ Enum in einen String?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy