2012-02-06 33 views
12

tengo una enumeración:¿Cómo verificar si una variable enum es válida?

enum myenum{ 
    typeA, 
    typeB, 
    typeC 
} myenum_t; 

Entonces, funciona una es para ser llamado con un parámetro de enumeración:

int myfunction(myenum_t param1) 
{ 
    switch(param1) 
    { 
    case typeA: 
    case typeB: 
    case typeC: 
     //do the work 
     break; 

    default: 
     printf("Invalid parameter"); 
    } 
    return 0; 
} 

Pero, como myenum_t crece con más y más valores, myfunction no parece muy elegante.

¿Existe alguna forma mejor de verificar si una enumeración es válida o no?

+0

No tener una copia de la norma, me gustaría tener arrancado por decir esto sin citarlo, por lo que voy a hacer un comentario: cada implementación C o C++ que he visto, los valores 'enum' se asignan en orden numérico creciente. Entonces todo lo que necesita hacer es agregar 'firstEnum = typeA, lastEnum = typeC' a su' enum' y luego comprobar el rango con 'if (int (inputEnum) int (lastEnum)) {/ * manejar error * /} '. –

Respuesta

18

Una convención común para esto es hacer algo como esto:

typedef enum { 
    typeA, 
    typeB, 
    typeC, 
    num_types 
} myenum_t; 

entonces usted puede comprobar para (t < num_types).

Si posteriormente agrega más enumeraciones, p.

typedef enum { 
    typeA, 
    typeB, 
    typeC, 
    typeD, 
    typeE, 
    num_types 
} myenum_t; 

continuación num_types se actualiza automáticamente y su código de comprobación de errores no tiene que cambiar.

+0

¿Qué significa 'myenum_t' después de su declaración enum? La [referencia de C#] (http://msdn.microsoft.com/en-us/library/sbbt4032.aspx) no parece mencionarlo; ninguno de sus ejemplos tiene nada después del corsé de cierre. –

+0

@PatrickM se requiere en C pero no en C++ o C# debido al hecho de que en C no se puede usar una etiqueta enum como tipo. Sin embargo, para tener sentido en la respuesta anterior, esperaría ver la palabra clave 'typedef' antes de la palabra clave' enum', declarando 'myenum_t' del mismo tipo que' enum myenum'. –

+0

Si esa enumeración es pública, entonces expones num_types al mundo. ¿Hay alguna forma de evitar eso? – duhanebel

3

Sí.

Deje que el compilador haga su trabajo, no eche int a un tipo enum y debe ser bueno.

+0

pero a veces tenemos que emitir –

5

se puede utilizar una enumeración bit a bit:

enum myEnum { 
    typeA = 1 << 0; 
    typeB = 1 << 1; 
    typeC = 1 << 2; 
} 

int myFunction(myEnum arg1) 
{ 
    int checkVal = typeA | typeB | typeC; 

    if (checkVal & arg1) 
    { 
     // do work here; 
    } 
    else 
    { 
     printf("invalid argument!"); 
    } 

    return 0; 
} 

Disculpe, parece haber leído mal la pregunta.

Parece que lo que quiere hacer es determinar si ha pasado un valor adecuado, no alguna opción inválida al azar. En ese caso, la opción más lógica es la siguiente:

if (arg1 < typeA || arg1 > typeC) 
    printf("invalid argument"); 

Esto es, por supuesto, asumiendo que no establece valores manuales para su enumeración, el cual, es bastante raro a menos que use enumeraciones bit a bit.

+0

¿Funciona esto si se agregan más valores a la enumeración? –

+3

"Pero, como myenum_t crece con más y más valores". ¿No hay una posibilidad de desbordamiento con '1 << n'? –

+0

@LuchianGrigore Tipo de. debe agregar el nombre de la variable a la declaración o, pero si olvida hacer eso, entonces no. Esta es solo una forma más concisa de verificar si se trata de un conjunto de tres valores. Y sí, podría desbordarse, según el tamaño entero de la máquina para la que estaba desarrollando. Sin embargo, en mi experiencia, es raro tener que lidiar con más de 32 valores diferentes en una enumeración, que es una buena estimación del máximo que tendría. –

0

No se puede también hacer algo como

enum myEnum {typeA,typeB, typeC}; 

int myFunction (myEnum arg1) { 
    if (arg1 >= typeA && arg1 <= typeC) { 
     // do work here 
    } else { 
     printf("invalid argument!"); 
    } 
    return 0; 
} 
+0

¿Hay alguna posibilidad de que el compilador optimice los controles? Si se agrega un * LastType *, entonces compruebe que 'arg1 dashesy

0

Desafortunadamente no hay una forma sencilla de hacerlo nivel de idioma (al menos con C), sólo tiene que asegurarse de que está utilizando sólo las variables definido a través de enum.

Aunque se puede habilitar una de las siguientes advertencias del compilador junto con -Werror:

  • -Wswitch
  • -Wswitch-default
  • -Wswitch-enum

Esto hace que la acumulación fallar si una de las enumeraciones se falta dentro del interruptor.

0

enumeraciones en C++ ya tienen tipos más fuertes que en C.

Tomemos el siguiente programa simple:

#include <iostream> 

enum E 
{ 
    A, 
    B 
}; 

void f(E e) 
{ 
} 

int main() 
{ 
    f(1); 
} 

Usando el compilador GCC voy a conseguir un este error:

 
enum.cpp: In function ‘int main()’: 
enum.cpp:15: error: invalid conversion from ‘int’ to ‘E’ 
enum.cpp:15: error: initializing argument 1 of ‘void f(E)’ 

Entonces, como puede ver, los miembros de la enumeración ya están marcados.

Si desea una comprobación de tipo aún más sólida y un compilador con capacidad C++ 11, puede usar una verificación de tipo más potente para enumeraciones, consulte http://en.wikipedia.org/wiki/C%2B%2B11#Strongly_typed_enumerations.

+0

¿Qué es 'e'? –

+1

@LightnessRacesinOrbit Realmente no tengo idea de lo que se supone que es, mi memoria es un poco confusa después de casi cuatro años ... :) Se supone * probablemente * como un entero literal. –

1

Un truco que he utilizado en el pasado:

enum foo {FIRST_FOO, BAR, BLETCH, BLURGA, BLAH, LAST_FOO}; 

y después comprobar para ver si su valor es > FIRST_FOO && < LAST_FOO .

Por supuesto, esto supone que no hay lagunas entre los valores de enumeración.

De lo contrario, no, no hay un buen método para hacer lo que está pidiendo (al menos en C).


Desde la última línea C Language Standard:

6.7.2.2 Enumeration specifiers
...
3 The identifiers in an enumerator list are declared as constants that have type int and may appear wherever such are permitted. 109) An enumerator with = defines its enumeration constant as the value of the constant expression. If the first enumerator has no = , the value of its enumeration constant is 0 . Each subsequent enumerator with no = defines its enumeration constant as the value of the constant expression obtained by adding 1 to the value of the previous enumeration constant. (The use of enumerators with = may produce enumeration constants with values that duplicate other values in the same enumeration.) The enumerators of an enumeration are also known as its members.
Cuestiones relacionadas