2008-08-30 4 views
4

Was ist der beste Ansatz, um zusätzliche Daten für Typedef enums in C zu definieren?Hinzufügen vordefinierter Daten für Typedef Enums in C

Beispiel:

typedef enum { 
    kVizsla = 0, 
    kTerrier = 3, 
    kYellowLab = 10 
} DogType; 

Nun würde Ich mag für jeden Namen definieren, zum Beispiel kVizsla sollte "vizsla" sein. Ich verwende derzeit eine Funktion, die eine Zeichenfolge mit einem großen Schalterblock zurückgibt.

Antwort

2

@dmckee: Ich denke, die vorgeschlagene Lösung ist gut, aber für einfache Daten (zB wenn nur der Name ist benötigt) könnte es mit automatisch generiertem Code ergänzt werden. Zwar gibt es viele Möglichkeiten, Code automatisch zu generieren, für etwas so einfaches wie dieses glaube ich, dass Sie ein einfaches XSLT schreiben könnten, das eine XML-Repräsentation der Enumeration aufnimmt und die Codedatei ausgibt.

Die XML würde von der Form:

<EnumsDefinition> 
    <Enum name="DogType"> 
     <Value name="Vizsla" value="0" /> 
     <Value name="Terrier" value="3" /> 
     <Value name="YellowLab" value="10" /> 
    </Enum> 
</EnumsDefinition> 

und der resultierende Code wäre etwas Ähnliches, was in seiner Lösung vorgeschlagen Dmckee.

Für Informationen, wie man solch ein XSLT schreibt, versuchen Sie oder suchen Sie es einfach in Google und finden Sie ein Tutorial, das passt. Das Schreiben von XSLT ist nicht viel Spaß IMO, aber es ist auch nicht so schlecht, zumindest für relativ einfache Aufgaben wie diese.

0

Das ist irgendwie eine offene Frage, aber ein Vorschlag, eine Karte mit der ENUM als Schlüsseltyp und die zusätzlichen Informationen in den Wert zu verwenden wäre. (Wenn Ihre Indizes fortlaufend sind, können Sie im Gegensatz zu dem Beispiel einen Sequenzcontainer statt einer Map verwenden).

1

Wenn Ihre Enumerationswerte dicht genug sind, können Sie ein Array definieren, das die Strings enthält und nur nachschlägt (verwenden Sie NULL für jeden übersprungenen Wert und fügen Sie einen speziellen Case-Handler zu Ihrer Suchroutine hinzu).

char *DogList[] = { 
    "vizsla", /* element 0 */ 
    NULL, 
    NULL, 
    NULL, 
    "terrier", /* element 3 */ 
    ... 
}; 

Dies ist ineffizient für spärliche Aufzählungen.

Auch wenn die Enumeration nicht dicht ist, können Sie ein Array von Strukturen verwenden, um die Zuordnung zu halten.

typedef struct DogMaps { 
    DogType index; 
    char * name; 
} DogMapt; 
DogMapt DogMap[] = { 
    {kVizsla, "vizsla"}, 
    {kTerrier, "terrier"}, 
    {kYellowLab, "yellow lab"}, 
    NULL 
}; 

Der zweite Ansatz ist sehr flexibel, aber es hat eine Suche durch die Zuordnung jedes Mal bedeuten müssen die Daten verwenden. Bei großen Datensätzen sollte anstelle eines Arrays ein B-Tree oder Hash verwendet werden.

Jede Methode kann verallgemeinert werden, um mehr Daten zu verbinden. In der ersten Verwendung ein Array von Strukturen, in der zweiten nur mehr Mitglieder der Struktur hinzufügen.

Sie möchten natürlich verschiedene Handler schreiben, um Ihre Interaktion mit diesen Datenstrukturen zu vereinfachen.


@Hershi Auf jeden Fall separaten Code und Daten. Die obigen Beispiele sollen klar und nicht funktional sein.

Ich weiß, zuzugeben, dass ich immer noch whitespace getrennte flache Dateien für diesen Zweck verwenden, anstatt die Art der strukturierten Eingabe, die Sie ausstellen, aber mein Produktionscode würde so viel von den Daten aus externen Quellen wie möglich lesen.


Warten Sie, ich sehe, dass Sie Code-Generierung meinen.

Sicher. Daran ist nichts falsch.

Ich vermute, wenn auch, dass der OP interessiert war, was den generierte Code soll wie folgt aussehen ...

3

Eine perfekte Passform für X() macros. Diese Arten von Makros können den C-Präprozessor verwenden, um Enums und Arrays aus derselben Quelle zu erstellen. Sie müssen dem #define, das das Makro X() enthält, nur neue Daten hinzufügen.

Ihr Beispiel geschrieben werden können wie folgt:

// All dog data goes in this list 
#define XDOGTYPE \ 
    X(kVizsla,0,"vizsla") \ 
    X(kTerrier,3,"terrier") \ 
    X(kYellowLab,10,"yellowlab") 

// Dog info 
typedef struct { 
    int val;  // Defined value 
    char * desc; // Text description 
} DogType; 

// Build an array index using the Names 
typedef enum { 
    #define X(Name,Val,Text)  Name, 
    XDOGTYPE 
    #undef X 
    MAXDOGS 
} DogIndex; 

// Build a lookup table of values 
DogType Dog[] = { 
    #define X(Name,Val,Text) {Val,Text}, 
    XDOGTYPE 
    #undef X 
}; 

// Access the values 
for (i=0; i < MAXDOGS; i++) 
    printf("%d: %s\n",Dog[i].val,Dog[i].desc);