2012-06-14 15 views
9

Unter der Annahme, dass ich dies:Prüfen, ob ein Wert in einem C enum definiert ist?

enum { A = 0x2E, B = 0x23, C = 0x40 }

es möglich zu überprüfen, ob x in enum definiert ist?

Ich mache es manuell: int isdef = (x == A || x == B || x == C); Aber ich möchte etwas dynamischer. GCC-extensions sind auch willkommen.

+1

nein, müssen Sie wahrscheinlich etwas verwenden, sonst wie eine Menge <> –

+1

@AndersK: Was ist ein 'set <>'? – Jack

Antwort

9

Diese Art einer modifizierten Version Ihrer Frage, aber je nachdem, was Sie tut, so etwas wie dies funktionieren könnte:

enum {A,B,C}; 
const int E[] = {0x2E,0x23,0x40}; 
// Or: 
// enum { A = 0x2E, B = 0x23, C = 0x40 }; 
// const int E[] = {A,B,C}; 

int isEnum(int x) 
{ 
    for(int i=0; i<(sizeof(E)/sizeof(*E)); i++) 
    { 
     if(E[i] == x){ return 1; } 
    } 
    return 0; 
} 

int main(void) 
{ 
    printf("Value of A: 0x%02x\n", E[A]); 
    // Or: 
    // printf("Value of A: 0x%02x\n", A); 

    printf("isEnum(0x2e): %s\n", isEnum(0x2e) ? "true" : "false"); 
    printf("isEnum(0x2f): %s\n", isEnum(0x2f) ? "true" : "false"); 
} 

die Ausgänge

 
Value of A: 0x2e 
isEnum(0x2e): true 
isEnum(0x2f): false 

EDIT: TJD schlug mich dazu, und sein Vorschlag, ein sortiertes Array zu verwenden und eine binäre Suche durchzuführen, würde Ihre Suchzeit von n auf log reduzieren (n).

+1

+1. Ich würde auch x-Makro machen, um sowohl enum als auch E [] zu generieren - keine Notwendigkeit, zwischen diesen beiden Datenstrukturen manuell zu synchronisieren. –

13

Nicht nach bestem Wissen. Ein Enum in C ist nur eine sauberere Alternative zu einer Reihe von

.

Wenn die ENUM groß ist und seine Werte passieren kontinuierlich sein, min/max Konstanten deklarieren und zu denen vergleichen:

enum { E_MIN = 0x2E, A = 0x2E, B = 0x23, C = 0x40 ..., E_MAX=0x100}; 

if(x >= MIN && x <= MAX) 
    ItsInEnum(); 
+3

Wenn die Werte diskontinuierlich sind, können Sie sie in ein konstantes Array (sortiert) stellen und eine schnelle binäre Suche durchführen, um festzustellen, ob sie darin enthalten ist. – TJD

+0

Da enums Kompilierzeitkonstanten sind, könnten Sie sogar eine perfekte Hashfunktion entwerfen und die Antwort in * constant * time finden. – Jens

+0

Die Hash-Berechnungszeit kann mit der eines manuellen Vergleichs vergleichbar sein. Für Enums ist das Verhalten von großen N nicht so relevant wie IMHO. –

1

Eine enum ist im Wesentlichen die gleiche Sache wie die Verwendung von Makros, um Konstanten zu definieren, außer dass die enum einen Satz von zugeordneten Konstanten in einen Datentyp umwandelt. Dies macht Ihren Code selbstdokumentierender, bietet jedoch keine zusätzliche Funktionalität.

Wenn Sie außerhalb des Bereichs von Standard C wagen, können einige Compiler mit enum zusätzliche Dinge tun, die sie mit Makros nicht tun können. Einige Debugger ordnen enum Variablen ihrem Namen zu, anstatt ihren Wert anzuzeigen. Außerdem bieten einige Compiler die Möglichkeit, Laufzeitprüfungen für Dinge wie Out-of-Bounds enum Werte hinzuzufügen. Dies entspricht im Wesentlichen dem angezeigten Code, nur der Compiler fügt ihn automatisch hinzu. Mit dem GreenHills C-Compiler ist diese Funktion mit der Compileroption -check=assignbound aktiviert. Ich bin mir nicht sicher, ob gcc sowas eingebaut hat oder nicht. Welchen Compiler benutzen Sie?

4

Um die akzeptierte Antwort zu erweitern, verwenden Sie X-Makros, um Enumeration und Array aus denselben Daten mit dem Präprozessor zu erstellen.

/* Only need to define values here. */ 
#define ENUM_VALUES \ 
    X(A, 0x2E) \ 
    X(B, 0x23) \ 
    X(C, 0x40) 

/* Preprocessor builds enum for you */ 
#define X(a, b) a = b, 
    enum { 
     ENUM_VALUES 
    }; 
#undef X 

/* Preprocessor builds array for you */ 
#define X(a, b) a, 
    const int E[] = { 
     ENUM_VALUES 
    }; 
#undef X 

/* Copied from accepted answer */ 
int isEnum(int x) 
{ 
    for(int i=0; i<sizeof(E);i++) 
    { 
     if(E[i] == x){ return 1; } 
    } 
    return 0; 
} 
4

Der einfachste Weg, dies zu tun ist:


enum { 
    MODE_A, 
    MODE_B, 
    MODE_C 
}; 

int modeValid(int mode) 
{ 
    int valid = 0; 

    switch(mode) { 
     case MODE_A: 
     case MODE_B: 
     case MODE_C: 
      valid = 1; 
    }; 

    return valid; 
} 

void setMode(int mode) 
{ 
    if (modeValid(mode)) { 
     // Blah, blah 
    } 
} 

int main(void) 
{ 
    setMode(1); // Okay 
    setMode(500); // Error 
} 
0

Wie bereits erwähnt, ist es nicht möglich ist, wenn eine Enumeration zu überprüfen, indem Sie direkt Bezug auf ein Aufzählungselement definiert ist. Es gibt jedoch eine sehr einfache Verknüpfung: Definieren Sie eine eindeutige Kennung, die jedem aufgezählten Typ zugeordnet ist.Wenn Sie dann, wenn ein Element der Aufzählung überprüfen möchten existiert, können Sie einfach überprüfen, ob die zugehörige Kennung definiert ist:

//Header File: 
typedef enum 
{ 
    ENUM_ELEMENT_1 = 0, 
    ENUM_ELEMENT_2 = 1, 
    ENUM_ELEMENT_3 = 2, 
    ENUM_ELEMENT_MAX 
} eEnumElement; 

#define ENUM_ELEMENT_DEFINED 1 

...

//Source file: 
void TaskOperateOnEnums(void) 
{ 
    #if defined(ENUM_ELEMENT_DEFINED) 
    eEnumElement Test = ENUM_ELEMENT_1; 
    ... 
    #endif 
} 
Verwandte Themen