it-swarm.com.de

So erhalten Sie die Aufzählung des Elementnamens anhand seines Werts

Ich habe einen Aufzählungstyp wie folgt deklariert:

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

Wie kann ich den Artikelnamen "Mo, Di usw." erhalten, wenn ich bereits den Artikelwert "0, 1 usw." habe?

Ich habe schon eine Funktion als diese

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

Und jetzt möchte ich die Ausgabe unten

Heute ist Mi, viel Spaß

26
Nano HE

Sie können nicht direkt, enum in C++ sind keine Java-Enums. 

Der übliche Ansatz besteht darin, einen std::map<WeekEnum,std::string> zu erstellen.

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

nein, Sie können den "Namen" nicht aus dem Wert in C++ ermitteln, da beim Kompilieren alle Symbole verworfen werden. 

Möglicherweise benötigen Sie diesen Weg X Macros

9
RolandXu

Eine Aufzählung ist eine Art inverses Array. Was ich glaube, dass du willst, ist 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.
7
Cosine

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

Hier ist ein weiterer netter Trick, um Enum mit X Macro zu definieren:

#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
3
Killzone Kid

Wie kann ich den Artikelnamen "Mo, Di usw." erhalten, wenn ich bereits die Artikelwert "0, 1 usw."

Bei einem älteren 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;
}

Con: 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 Funktion entsprechend anpassen. Ich nehme an, das trifft sogar für eine std :: map zu. 

Ich erinnere mich vage, dass wir ein Hilfsprogramm gefunden haben, um den Funktionscode aus dem Enum-Code zu generieren. Die Länge der Auflistungstabelle war auf mehrere Hundert angewachsen ... und irgendwann ist es vielleicht eine gute Wahl, Code zum Schreiben von Code zu schreiben. 


Hinweis - 

bei einer Verbesserung des eingebetteten Systems ersetzte mein Team viele Tabellen (100+?) nullterminierter Zeichenfolgen, die zum Zuordnen von enum Int-Werten zu ihren Textzeichenfolgen verwendet wurden.

Das Problem bei den Tabellen war, dass ein Wert außerhalb des Bereichs oft nicht bemerkt wurde, da viele dieser Tabellen in einem Bereich des Codes/Speichers zusammengefasst wurden, sodass ein Wert außerhalb des Bereichs über das genannte Tabellenende und die genannten Werte hinausreicht gab einen nullterminierten String aus einer nachfolgenden Tabelle zurück. 

Mit der Anweisung function-with-switch konnten wir auch eine Assertierung in der default-Klausel des Switches hinzufügen. Die Asserts fanden während des Tests einige weitere Codierungsfehler und unsere Assessments wurden in ein statisches RAM-Systemprotokoll gebunden, das unsere Feldtechniker durchsuchen konnten. 

1
2785528

Wenn Sie wissen, dass die tatsächlichen Enum-Labels mit ihren Werten korrelieren, können Sie Container und std::string_view von C++ 17 verwenden, um mit dem Operator [] schnell auf Werte und deren Zeichenfolgendarstellungen zuzugreifen, während Sie sie selbst verfolgen. std::string_view reserviert Speicher nur bei der Erstellung. Sie können auch mit static constexpr gekennzeichnet werden, wenn sie zur Laufzeit verfügbar sein sollen, um mehr Leistung zu sparen. Diese kleine Konsolen-App sollte ziemlich schnell sein.

#include <iostream>
#include <string_view>
#include <Tuple>    
int main() {
    enum class Weekdays { //default behavior starts at 0 and iterates by 1 per entry
        Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday
    };

    static constexpr std::string_view Monday    = "Monday";
    static constexpr std::string_view Tuesday   = "Tuesday";
    static constexpr std::string_view Wednesday = "Wednesday";
    static constexpr std::string_view Thursday  = "Thursday";
    static constexpr std::string_view Friday    = "Friday";
    static constexpr std::string_view Saturday  = "Saturday";
    static constexpr std::string_view Sunday    = "Sunday";
    static constexpr std::string_view opener    = "enum[";
    static constexpr std::string_view closer    = "] is ";
    static constexpr std::string_view semi      = ":";

    std::pair<Weekdays, std::string_view> Weekdays_List[] = {
        std::make_pair(Weekdays::Monday,    Monday),
        std::make_pair(Weekdays::Tuesday,   Tuesday),
        std::make_pair(Weekdays::Wednesday, Wednesday),
        std::make_pair(Weekdays::Thursday,  Thursday),
        std::make_pair(Weekdays::Friday,    Friday),
        std::make_pair(Weekdays::Saturday,  Saturday),
        std::make_pair(Weekdays::Sunday,    Sunday)
    };

    for (int i=0;i<sizeof(Weekdays_List)/sizeof(Weekdays_List[0]);i++) {
        std::cout<<opener<<i<<closer<<Weekdays_List[(int)i].second<<semi\
        <<(int)Weekdays_List[(int)i].first<<std::endl;
    }    
    return 0;
}

Ausgabe: 

enum[0] is Monday:0
enum[1] is Tuesday:1
enum[2] is Wednesday:2
enum[3] is Thursday:3
enum[4] is Friday:4
enum[5] is Saturday:5
enum[6] is Sunday:6
0

Ich war mit einer Technik, die den X-Makros ähnelt, auf die @RolandXu verweist, sehr erfolgreich. Auch den Stringize-Operator haben wir intensiv genutzt. Die Technik verringert den Wartungs-Albtraum, wenn Sie über eine Anwendungsdomäne verfügen, in der Elemente sowohl als Zeichenfolgen als auch als numerische Token angezeigt werden.

Es ist besonders praktisch, wenn maschinenlesbare Dokumentation verfügbar ist, damit die Makrozeilen X(...) automatisch generiert werden können. Eine neue Dokumentation würde sofort zu einem konsistenten Programmupdate führen, das die Zeichenfolgen, Aufzählungen und die Wörterbücher umfasst, die zwischen ihnen in beide Richtungen übersetzt werden. (Wir haben es mit PCL6-Token zu tun).

Und obwohl der Präprozessor-Code ziemlich hässlich aussieht, können all diese technischen Merkmale in den Header-Dateien versteckt sein, die nie wieder berührt werden müssen, und auch die Quelldateien nicht. Alles ist typsicher. Das einzige, was sich ändert, ist eine Textdatei, die alle X(...) - Zeilen enthält und möglicherweise automatisch generiert wird.

0