2012-06-14 10 views
9

Suponiendo que tengo esto:Verificar si un valor está definido en una Cum?

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

es posible verificación si x se define en enum?

Lo estoy haciendo manualmente: int isdef = (x == A || x == B || x == C); Pero quiero algo más dinámico. GCC-extensions son bienvenidos también.

+1

no, es probable que tenga que usar algo más bien como un conjunto <> –

+1

@AndersK: ¿qué es un 'set <>'? – Jack

Respuesta

9

Esta es una especie de una versión modificada de su pregunta, pero dependiendo de lo que estamos haciendo, algo como esto podría funcionar:

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"); 
} 

que emite

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

EDITAR: TJD me ganó, y su sugerencia de utilizar una matriz ordenada y realizar búsquedas binarias disminuiría el tiempo de búsqueda de n para iniciar sesión (n).

+1

+1. También haría que x-macro genere tanto enum como E [] - no es necesario sincronizar manualmente entre estas dos estructuras de datos. –

13

A mi leal saber y entender. Una enumeración en C es solo una alternativa más limpia a una serie de

#define A 0x2E 

declaraciones.

Si la enumeración es grande y sus valores resultan ser continua, declarar min constantes/max y compara a los:

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

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

Si los valores son discontinuos, puede ponerlos en una matriz constante (ordenada) y hacer una búsqueda binaria rápida para encontrar si está allí. – TJD

+0

Dado que las enumeraciones son constantes de tiempo de compilación, incluso podría diseñar una función hash perfecta y encontrar la respuesta en tiempo * constante *. – Jens

+0

El tiempo de cálculo del hash puede ser comparable al de la comparación manual. Para las enumeraciones, el comportamiento de N grande no es tan relevante en mi humilde opinión. –

1

Un enum es esencialmente lo mismo que usar macros para definir constantes, excepto que el enum envuelve un conjunto de constantes asociadas en un tipo de datos. Esto hace que su código sea más autodocumentado, pero en realidad no proporciona ninguna funcionalidad adicional.

Si se aventura fuera del ámbito de la norma C, algunos compiladores pueden hacer cosas adicionales con enum que no pueden hacer con las macros. Algunos depuradores asignarán las variables enum a su nombre en lugar de mostrar su valor. Además, algunos compiladores ofrecen la posibilidad de agregar comprobaciones de tiempo de ejecución para cosas como valores enum fuera de límites. Esto es esencialmente lo mismo que el código que muestra, solo el compilador lo agrega automáticamente. Con el compilador C de GreenHills, esta característica se habilita con la opción del compilador -check=assignbound. No estoy seguro si gcc tiene algo así como incorporado o no. Qué compilador estas usando?

4

Para ampliar la respuesta aceptada, use X-macros para construir su enumeración y matriz a partir de los mismos datos utilizando el preprocesador.

/* 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

La forma más sencilla de hacerlo es:


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

Como ya se ha señalado, no es posible comprobar si una enumeración se define por referirse directamente a un miembro de la enumeración. Sin embargo, hay un atajo muy simple: defina un identificador único asociado con cada tipo enumerado.Entonces, cuando se quiere comprobar si existe un elemento de la enumeración, sólo tiene que comprobar si se define el identificador asociado:

//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 
} 
Cuestiones relacionadas