2010-08-11 4 views
7

Gibt es eine Möglichkeit, den Namen eines enum Wert anzuzeigen? sagen wir:Generische Methode zum Anzeigen von Enum-Wert-Namen

enum fuits{ 
    APPLE, 
    MANGO, 
    ORANGE, 
}; 

main(){ 
enum fruits xFruit = MANGO; 
... 
printf("%s",_PRINT_ENUM_STRING(xFruit)); 
... 
} 

den Präprozessor mit

#define _PRINT_ENUM_STRING(x) #x 

wird nicht funktionieren, da wir den Wert der Variablen ‚x‘ müssen erhalten und es dann in einen String zu konvertieren. Ist das in c/C++ überhaupt möglich?

+0

Mögliche duplizieren http://stackoverflow.com/questions/3342726/c-print-out-enum-value-as-text –

+1

Dies ist ein FAQ ist alles über die Intertubes und meistens wahrscheinlich ein Betrogener hier, obwohl ich nicht überprüft habe. Antwort: Nein, es kann nicht getan werden (ohne durch Reifen zu springen, wie @Naveen suggeriert und das Risiko besteht, aus dem Takt zu geraten. Wenn Sie bereit sind, dieses Risiko einzugehen, scheinen einige Leute diese Lösung zu verwenden. Es ist besser als nichts , aber es ist verlockendes Schicksal ...). – Mawg

+0

@Eugen Constantin Dinca Diese Frage ist nur C++, während das OP hier eine C-Lösung zu haben scheint. – schot

Antwort

7

Sie könnten den Prä-Prozessor verwenden, dies zu tun, ich glaube, diese Technik X-Macros genannt wird:

/* fruits.def */ 
X(APPLE) 
X(MANGO) 
X(ORANGE) 

/* file.c */ 
enum fruits { 
#define X(a) a, 
#include "fruits.def" 
#undef X 
}; 

const char *fruit_name[] = { 
#define X(a) #a, 
#include "fruits.def" 
#undef X 
}; 

Beachten Sie, dass der letzte Eintrag ein Komma enthält, die in C99 erlaubt ist (aber nicht in C89). Wenn das ein Problem ist, können Sie Sentinal-Werte hinzufügen. Es ist auch möglich, das Makro komplizierter indem sie mehrere Argumente für benutzerdefinierte Namen oder ENUM-Werte zu machen, etc:

X(APPLE, Apple, 2) 
#define X(a,b,c) a = c,  /* in enum */ 
#define X(a,b,c) [c] = #b,  /* in name array */ 

Einschränkungen: Sie können keine negativen Konstanten und Ihr Array ist sizeof (char *) * largest_constant. Aber Sie könnten Tabelle unter Verwendung eines zusätzlichen Lookup um beide arbeiten:

int map[] = { 
#define X(a,b,c) c, 
#include "fruits.def" 
#undef X 
}; 

Dies ist natürlich nicht funktioniert. Was bedeutet Arbeit für die Namen einen zusätzlichen Satz enum Konstanten als Schlüssel zu erzeugen:

enum fruits { 
#define X(a,b,c) a ## _KEY, 
#include "fruits.def" 
#undef X 
#define X(a,b,c) a = c, 
#include "fruits.def" 
#undef X 
}; 

Jetzt können Sie den Namen X(PINEAPPLE, Pineapple, -40) unter Verwendung fruit_name[PINEAPPLE_KEY] finden.

Die Leute haben festgestellt, dass sie die zusätzliche Include-Datei nicht mögen. Sie benötigen diese zusätzliche Datei nicht, Sie verwenden auch eine #define. Dies kann besser geeignet für kleine Listen sein:

#define FRUIT_LIST X(APPLE) X(ORANGE) 

Und #include "fruits.def mit FRUIT_LIST in den vorherigen Beispielen ersetzen.

+0

Das ist der beste Weg, den ich kenne. Ich habe eine ähnliche Technik für Fehler-Strings mit einem 2-Argument-X-Makro verwendet: 'X (name, desc)' wobei das Makro entweder auf den Fehlercode (analog zu 'errno'-Werten) oder eine beschreibende Zeichenfolge in Abhängigkeit von where erweitert wurde Die Fehlerlistendatei wurde hinzugefügt. –

+1

+1. Das ist fast mein üblicher Hack, wenn ich das Enum in einem Perl-Skript definiere, das das Enum in eine .h-Datei und das passende Translation-Array in eine .c-Datei schreibt. Mein Weg erfordert einen benutzerdefinierten Build-Schritt, der einfach mit make, aber schwerer in einer vollständigen IDE ist. – RBerteig

+0

Ich mag es nicht. Kann manchmal nützlich sein, aber ich würde es nicht überbeanspruchen. Vielleicht würde ich es für große und häufig veränderte Enums verwenden. Die Kosten dafür sind zu groß. – adf88

1

In diesem Fall können Sie ein Mapping verwenden.

char *a[10] = { "APPLE","MANGO","ORANGE"}; 

printf("%s",a[xFruit]); 

Ja der Präprozessor wird nicht funktionieren, wenn Sie den genauen Enum-Wert angeben.

Weitere Informationen finden Sie auch unter this question.

0

I Präprozessor Programmierung verwendet haben erfolgreich ein Makro dieser Art zu erhalten:

DEFINE_ENUM(Fruits, (Apple)(Mango)(Orange)); 

Es tut ein bisschen mehr als nur die Namen drucken, aber es leicht zu 2 Schalter vereinfacht werden könnte, falls erforderlich.

Es basiert auf Boost.Preprocessor Einrichtungen (insbesondere BOOST_PP_SEQ_FOREACH), die ein Muss für Präprozessor-Programmierung ist, und ich finde es viel eleganter als die X Einrichtung und ihre Datei Reinclusion System.

-1

 public enum LDGoalProgressUpdateState 
    {

[Description("Yet To Start")] 
    YetToStart = 1, 
    [Description("In Progress")] 
    InProgress = 2, 
    [Description("Completed")] 
    Completed = 3 
} 


    var values = (ENUMList[])Enum.GetValues(typeof(ENUMList)); 
    var query = from name in values 
       select new EnumData//EnumData is a Modal or Entity 
       { 
        ID = (short)name, 
        Name = GetEnumDescription(name)//Description of Particular Enum Name 
       }; 
    return query.ToList(); 

Region HelperMethods

public static string GetEnumDescription(Enum value) { FieldInfo fi = value.GetType().GetField(value.ToString()); DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false); if (attributes != null && attributes.Length > 0) return attributes[0].Description; else return value.ToString(); } #endregion
+0

Dies scheint nicht C oder C++ zu sein, wie in der Frage – jcoder

+0

gefordert Dieser Code bezieht sich auf C# –

Verwandte Themen