Gibt es eine Möglichkeit, Enumeratornamen in C in Zeichenfolgen umzuwandeln?
Eine Möglichkeit, den Präprozessor die Arbeit machen zu lassen. Außerdem wird sichergestellt, dass Ihre Aufzählungen und Zeichenfolgen synchron sind.
#define FOREACH_FRUIT(FRUIT) \
FRUIT(apple) \
FRUIT(orange) \
FRUIT(grape) \
FRUIT(banana) \
#define GENERATE_ENUM(ENUM) ENUM,
#define GENERATE_STRING(STRING) #STRING,
enum FRUIT_ENUM {
FOREACH_FRUIT(GENERATE_ENUM)
};
static const char *FRUIT_STRING[] = {
FOREACH_FRUIT(GENERATE_STRING)
};
Nachdem der Präprozessor fertig ist, haben Sie:
enum FRUIT_ENUM {
apple, orange, grape, banana,
};
static const char *FRUIT_STRING[] = {
"apple", "orange", "grape", "banana",
};
Dann könnten Sie so etwas tun wie:
printf("enum apple as a string: %s\n",FRUIT_STRING[apple]);
Wenn der Anwendungsfall buchstäblich nur den Namen der Aufzählung druckt, fügen Sie die folgenden Makros hinzu:
#define str(x) #x
#define xstr(x) str(x)
Dann mach:
printf("enum apple as a string: %s\n", xstr(apple));
In diesem Fall scheint das zweistufige Makro überflüssig zu sein. Aufgrund der Funktionsweise der Stringifizierung in C ist dies jedoch in einigen Fällen erforderlich. Angenommen, wir möchten ein #define mit einer Aufzählung verwenden:
#define foo apple
int main() {
printf("%s\n", str(foo));
printf("%s\n", xstr(foo));
}
Die Ausgabe wäre:
foo
apple
Dies liegt daran, dass str die Eingabe foo stringifiziert, anstatt sie zu apple zu erweitern. Mit xstr wird zuerst die Makroerweiterung durchgeführt, dann wird das Ergebnis stringifiziert.
Weitere Informationen finden Sie unter Stringifizierung .
#define GENERATE_ENUM(ENUM) PREFIX##ENUM,
In einer Situation, in der Sie dies haben:
Ich möchte dies in die Header-Datei einfügen, in der die Aufzählung definiert ist:
quelle
enumToString(apple)
als zu tippen"apple"
? Es ist nicht so, dass es irgendwo irgendeine Art von Sicherheit gibt. Es sei denn, mir fehlt etwas, was Sie hier vorschlagen, ist sinnlos und es gelingt nur, Code zu verschleiern.Es gibt keinen einfachen Weg, dies direkt zu erreichen. Aber P99 hat Makros , die es Ihnen ermöglichen , diese Art von Funktion zu erstellen automatisch:
in einer Header-Datei und
In einer Kompilierungseinheit (.c-Datei) sollte dann der Trick ausgeführt werden, in diesem Beispiel würde dann die Funktion aufgerufen
color_getname
.quelle
Ich habe einen C-Präprozessor-Trick gefunden, der denselben Job ausführt, ohne eine dedizierte Array-Zeichenfolge zu deklarieren (Quelle: http://userpage.fu-berlin.de/~ram/pub/pub_jf47ht81Ht/c_preprocessor_applications_en ).
Sequentielle Aufzählungen
Nach der Erfindung von Stefan Ram können sequentielle Aufzählungen (ohne explizite Angabe des Index, z. B.
enum {foo=-1, foo1 = 1}
) wie dieser geniale Trick realisiert werden:Dies ergibt das folgende Ergebnis:
Nicht sequentielle Aufzählungen
Da ich Fehlercode-Definitionen als Array-Zeichenfolge zuordnen wollte, damit ich die rohe Fehlerdefinition an den Fehlercode anhängen kann (z. B.
"The error is 3 (LC_FT_DEVICE_NOT_OPENED)."
), habe ich den Code so erweitert, dass Sie den erforderlichen Index für die jeweiligen Aufzählungswerte leicht ermitteln können ::In diesem Beispiel generiert der C-Präprozessor den folgenden Code :
Dies führt zu den folgenden Implementierungsfunktionen:
quelle
Sie müssen sich nicht auf den Präprozessor verlassen, um sicherzustellen, dass Ihre Aufzählungen und Zeichenfolgen synchron sind. Für mich ist die Verwendung von Makros schwieriger zu lesen.
Verwenden von Enum und einer Reihe von Zeichenfolgen
Hinweis: Die Zeichenfolgen im
fruit_str
Array müssen nicht in derselben Reihenfolge wie die Aufzählungselemente deklariert werden.Wie man es benutzt
Hinzufügen einer Überprüfung der Kompilierungszeit
Wenn Sie Angst haben, eine Zeichenfolge zu vergessen, können Sie die folgende Prüfung hinzufügen:
Bei der Kompilierung wird ein Fehler gemeldet, wenn die Anzahl der Aufzählungselemente nicht mit der Anzahl der Zeichenfolgen im Array übereinstimmt.
quelle
Eine solche Funktion ohne Validierung der Aufzählung ist eine Kleinigkeit gefährlich. Ich schlage vor, eine switch-Anweisung zu verwenden. Ein weiterer Vorteil besteht darin, dass dies für Aufzählungen mit definierten Werten verwendet werden kann, z. B. für Flags mit den Werten 1,2,4,8,16 usw.
Fügen Sie außerdem alle Aufzählungszeichenfolgen in einem Array zusammen: -
Definieren Sie die Indizes in einer Header-Datei: -
Auf diese Weise können Sie leichter verschiedene Versionen erstellen, beispielsweise wenn Sie internationale Versionen Ihres Programms in anderen Sprachen erstellen möchten.
Verwenden eines Makros, auch in der Header-Datei: -
Machen Sie eine Funktion mit einer switch-Anweisung, dies sollte a zurückgeben,
const char *
da die Zeichenfolgen statische consts: -Bei der Programmierung mit Windows können die ID_-Werte Ressourcenwerte sein.
(Wenn Sie C ++ verwenden, können alle Funktionen denselben Namen haben.
)
quelle
Eine einfachere Alternative zu Hokyos Antwort "Nicht-sequentielle Aufzählungen", basierend auf der Verwendung von Bezeichnern zum Instanziieren des Zeichenfolgenarrays:
quelle
Normalerweise mache ich das:
quelle