So erhalten Sie den Namen des Aufzählungselements aus seinem Wert

Lesezeit: 7 Minuten

Benutzer-Avatar
Nano HE

Ich habe einen Aufzählungstyp als diesen deklariert,

enum WeekEnum
{
Mon = 0;
Tue = 1;
Wed = 2;
Thu = 3;
Fri = 4;
Sat = 5;
Sun = 6;
};

Wie bekomme ich den Item-Namen „Mo, Di, etc“ wenn ich bereits den Item-Wert „0, 1, etc.“ habe?

Ich habe bereits eine Funktion als diese

Log(Today is "2", enjoy! );

Und jetzt möchte ich die Ausgabe unten

Heute ist Mi, viel Spaß

  • Mögliches Duplikat von C++: Aufzählungswert als Text ausgeben

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

    11. Dezember 2016 um 14:56 Uhr

Sie können nicht direkt enum in C++ sind nicht wie Java-Enumerationen.

Der übliche Ansatz besteht darin, eine std::map<WeekEnum,std::string>.

std::map<WeekEnum,std::string> m;
m[Mon] = "Monday";
//...
m[Sun] = "Sunday";

  • Ich würde wahrscheinlich ein Array vor einer Karte verwenden.

    – Muhende Ente

    30. Juli 2012 um 1:27 Uhr

  • @Darwyn: Ein Array ist unbedingt besser, solange Sie die richtige Größe reservieren. Das Lesen oder Schreiben ist eine triviale Indexoperation, und es gibt niemals Einfügungen oder Löschungen.

    – Muhende Ente

    18. August 2017 um 20:30 Uhr


  • @Darwyn: Die Suche in einer Hashtabelle ist O (1), aber sie hat eine große Konstante für die Hash-Gleichung. Die Suchoperation auf dem Array ist buchstäblich eine direkte Indizierung, es gibt keine Suche oder Gleichung. m[Mon] wird vom Compiler behandelt als m[1], was normalerweise ein einzelner Opcode ist. Sie denken daran, im Array nach Wert und nicht nach Index zu suchen.

    – Muhende Ente

    18. August 2017 um 21:30 Uhr

  • @MooingDuck Du hast Recht, ich denke fälschlicherweise an die Suche nach Wert und nicht nach Index. Vielen Dank.

    – Darwyn

    18. August 2017 um 22:43 Uhr

  • Die Verwendung eines Arrays impliziert wahrscheinlich auch, dass die Aufzählungswerte zusammenhängend sind. Obwohl die meisten in der Praxis deklarierten Aufzählungen wahrscheinlich zusammenhängend sind, gibt es nichts in der Sprache, das dies vorschreibt.

    – Saxbophon

    20. April 2019 um 12:17 Uhr

Benutzer-Avatar
Killzone-Kind

Hier ist ein weiterer netter Trick, um Enum zu definieren X-Makro:

#include <iostream>

#define WEEK_DAYS \
X(MON, "Monday", true) \
X(TUE, "Tuesday", true) \
X(WED, "Wednesday", true) \
X(THU, "Thursday", true) \
X(FRI, "Friday", true) \
X(SAT, "Saturday", false) \
X(SUN, "Sunday", false)

#define X(day, name, workday) day,
enum WeekDay : size_t
{
    WEEK_DAYS
};
#undef X

#define X(day, name, workday) name,
char const *weekday_name[] =
{
    WEEK_DAYS
};
#undef X

#define X(day, name, workday) workday,
bool weekday_workday[]
{
    WEEK_DAYS
};
#undef X

int main()
{
    std::cout << "Enum value: " << WeekDay::THU << std::endl;
    std::cout << "Name string: " << weekday_name[WeekDay::THU] << std::endl;
    std::cout << std::boolalpha << "Work day: " << weekday_workday[WeekDay::THU] << std::endl;

    WeekDay wd = SUN;
    std::cout << "Enum value: " << wd << std::endl;
    std::cout << "Name string: " << weekday_name[wd] << std::endl;
    std::cout << std::boolalpha << "Work day: " << weekday_workday[wd] << std::endl;

    return 0;
}

Live-Demo: https://ideone.com/bPAVTM

Ausgänge:

Enum value: 3
Name string: Thursday
Work day: true
Enum value: 6
Name string: Sunday
Work day: false

  • Am Ende habe ich diesen Trick für eine Aufzählung in einem freigegebenen Header verwendet. Da es jedoch geteilt wurde, musste ich das Array in eine Inline-Funktion ändern, die den String zurückgibt, wenn der Wert übereinstimmt. (wie in “if parameter == day return name;”). Dieser Ansatz ist so hässlich wie es nur geht, aber die Wartbarkeit ist erstklassig.

    – Richard

    20. Dezember 2020 um 12:13 Uhr

  • Können Sie dies auf stark typisierte Weise tun? Ähnlich zu enum class?

    – Weston McNamara

    11. Januar um 19:05 Uhr

  • @WestonMcNamara ja, genauso enum class WeekDay { WEEK_DAYS ....

    – Matthias

    4. März um 16:26 Uhr

Benutzer-Avatar
RolandXu

Nein, Sie haben keine Möglichkeit, den “Namen” aus dem Wert in C++ zu erhalten, da alle Symbole während der Kompilierung verworfen werden.

Möglicherweise benötigen Sie diesen Weg X-Makros

  • Diese Antwort ist zu “total”. Es gibt keinen Grund, warum __ENUM_NAME__(x) existiert nicht, da es Sachen wie gibt __FUNCTION__, __PRETTY_FUNCTION__ usw. schon. Die Compiler-Jungs könnten eine ähnliche Lösung für Enums anbieten. Rust hat etwas ähnliches mit #[derive(Debug)] oder #[derive(Display)]. Haskell hat deriving Show als Compiler-Goodie, das dasselbe tut.

    – BitTickler

    30. Mai um 13:31 Uhr


Sie können einen Operator definieren, der die Ausgabe durchführt.

std::ostream& operator<<(std::ostream& lhs, WeekEnum e) {
    switch(e) {
    case Monday: lhs << "Monday"; break;
    .. etc
    }
    return lhs;
}

Benutzer-Avatar
Kosinus

Eine Enumeration ist so etwas wie ein inverses Array. Ich glaube, Sie wollen Folgendes:

const char * Week[] = { "", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };  // The blank string at the beginning is so that Sunday is 1 instead of 0.
cout << "Today is " << Week[2] << ", enjoy!";  // Or whatever you'de like to do with it.

  • Enum und Array sind zwei sehr unterschiedliche Dinge.

    – Meister Yoda

    1. Juni 2016 um 5:48 Uhr

  • Das ist richtig. Während eine Aufzählung (Quell-)Strings mit Zahlen abgleicht, könnte ein Array Zahlen mit Strings abgleichen. (Sehen Sie die Beziehung?) Der Titel von OP kann nicht direkt erreicht werden, aber ihr Kernproblem kann es. Da ihr Beispiel Namen in numerischer Reihenfolge enthält, kann sie ein Array anstelle einer std::map verwenden (die schwerer ist). Daher ist ein Array möglicherweise genau das, was OP braucht, obwohl es ihre Titelfrage nicht beantwortet hat.

    – Kosinus

    2. Juni 2016 um 14:46 Uhr

  • Ich habe dies abgelehnt, weil es nutzlos ist, wenn Enum-Wert und Array-Index nicht übereinstimmen

    – Elvis Dukaj

    14. April 2020 um 12:52 Uhr

Wie bekomme ich den Item-Namen „Mo, Di, etc“ wenn ich bereits den Item-Wert „0, 1, etc.“ habe?

Auf etwas älterem C-Code (vor einiger Zeit) fand ich Code analog zu:

std::string weekEnumToStr(int n)
{
   std::string s("unknown");
   switch (n)
   {
   case 0: { s = "Mon"; } break;
   case 1: { s = "Tue"; } break;
   case 2: { s = "Wed"; } break;
   case 3: { s = "Thu"; } break;
   case 4: { s = "Fri"; } break;
   case 5: { s = "Sat"; } break;
   case 6: { s = "Sun"; } break;
   }
   return s;
}

Nachteil: Dies stellt eine “pathologische Abhängigkeit” zwischen den Aufzählungswerten und der Funktion her … das heißt, wenn Sie die Aufzählung ändern, müssen Sie die entsprechende Funktion ändern. Ich nehme an, das gilt sogar für eine std::map.

Ich erinnere mich vage, dass wir ein Dienstprogramm gefunden haben, um den Funktionscode aus dem Enum-Code zu generieren. Die Länge der Enum-Tabelle war auf mehrere hundert angewachsen … und irgendwann ist es vielleicht eine gute Wahl, Code zu schreiben, um Code zu schreiben.


Notiz –

Bei einer Verbesserung des eingebetteten Systems ersetzte mein Team viele Tabellen (über 100?) mit nullterminierten Zeichenfolgen, die verwendet wurden, um Enum-Int-Werte ihren Textzeichenfolgen zuzuordnen.

Das Problem mit den Tabellen war, dass ein Wert außerhalb des gültigen Bereichs oft nicht bemerkt wurde, da viele dieser Tabellen in einem Code-/Speicherbereich gesammelt wurden, sodass ein Wert außerhalb des gültigen Bereichs über das/die benannte(n) Tabellenende(n) hinausreichte gab eine nullterminierte Zeichenfolge aus einer nachfolgenden Tabelle zurück.

Die Verwendung der function-with-switch-Anweisung ermöglichte es uns auch, ein Assert in der Standardklausel des Schalters hinzuzufügen. Die Asserts fanden während des Tests mehrere weitere Codierungsfehler, und unsere Asserts wurden in ein statisches RAM-Systemprotokoll eingebunden, das unsere Außendiensttechniker durchsuchen konnten.

  • Enum und Array sind zwei sehr unterschiedliche Dinge.

    – Meister Yoda

    1. Juni 2016 um 5:48 Uhr

  • Das ist richtig. Während eine Aufzählung (Quell-)Strings mit Zahlen abgleicht, könnte ein Array Zahlen mit Strings abgleichen. (Sehen Sie die Beziehung?) Der Titel von OP kann nicht direkt erreicht werden, aber ihr Kernproblem kann es. Da ihr Beispiel Namen in numerischer Reihenfolge enthält, kann sie ein Array anstelle einer std::map verwenden (die schwerer ist). Daher ist ein Array möglicherweise genau das, was OP braucht, obwohl es ihre Titelfrage nicht beantwortet hat.

    – Kosinus

    2. Juni 2016 um 14:46 Uhr

  • Ich habe dies abgelehnt, weil es nutzlos ist, wenn Enum-Wert und Array-Index nicht übereinstimmen

    – Elvis Dukaj

    14. April 2020 um 12:52 Uhr

Benutzer-Avatar
Rick-Rick-Rick

Auf GCC kann es so aussehen:

const char* WeekEnumNames [] = {
    [Mon] = "Mon",
    [Tue] = "Tue",
    [Wed] = "Wed",
    [Thu] = "Thu",
    [Fri] = "Fri",
    [Sat] = "Sat",
    [Sun] = "Sun",
};

1019360cookie-checkSo erhalten Sie den Namen des Aufzählungselements aus seinem Wert

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

Privacy policy