2012-02-06 17 views
12

Ho un enum:Come verificare se una variabile enum è valida?

enum myenum{ 
    typeA, 
    typeB, 
    typeC 
} myenum_t; 

Poi, funzioni deve essere chiamato con un parametro enum:

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

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

Ma, come myenum_t cresce con sempre più valori, myfunction non sembra così elegante.

C'è un modo migliore per verificare se un enum è valido o no?

+0

Non avendo una copia dello standard, mi sarei strappato per dire questo senza citare, in modo ce la farò un commento: In Ogni implementazione C o C++ che ho visto, i valori di 'enum' sono assegnati in ordine numerico crescente. Quindi tutto ciò che devi fare è aggiungere 'firstEnum = typeA, lastEnum = typeC' al tuo' enum' e quindi range control con 'if (int (inputEnum) int (lastEnum)) {/ * gestisce l'errore * /} '. –

risposta

18

Una convenzione comune per questo è di fare qualcosa di simile:

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

Quindi è possibile verificare la presenza di (t < num_types).

Se successivamente aggiungi più enumerazioni, ad es.

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

poi num_types si aggiorna automaticamente e il vostro controllo degli errori di codice non ha bisogno di cambiare.

+0

Cosa significa "myenum_t" dopo la dichiarazione enum? Il [C# Reference] (http://msdn.microsoft.com/en-us/library/sbbt4032.aspx) non sembra menzionarlo; nessuno dei loro esempi ha nulla dopo la parentesi di chiusura. –

+0

@PatrickM è richiesto in C ma non in C++ o C# a causa del fatto che in C non è possibile utilizzare un tag enum come tipo. Comunque, per avere un senso nella risposta di cui sopra, mi aspetterei di vedere la parola chiave 'typedef' prima della parola chiave' enum', dichiarando 'myenum_t' come lo stesso tipo di' enum myenum'. –

+0

Se l'enum è pubblico, allora stai esponendo num_types al mondo. C'è un modo per aggirare questo? – duhanebel

3

Sì.

Lascia che il compilatore faccia il suo lavoro, non trasmettere int a un tipo enum e si dovrebbe essere buono.

+0

ma a volte è necessario eseguire il cast –

5

si potrebbe usare un enum 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; 
} 

Mi scusi, mi sembra di aver letto la domanda sbagliata.

Sembra che ciò che si vuole fare è determinare se si è passato un valore corretto, non un'opzione casuale non valida. In tal caso, l'opzione più logica è questa:

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

Questo è, naturalmente, a patto che non si imposta i valori manuali per la vostra enum, che, è abbastanza raro a meno di utilizzare enumerazioni bit per bit.

+0

Funziona se vengono aggiunti più valori all'enumerazione? –

+3

"Ma come myenum_t cresce con sempre più valori". Non c'è una possibilità di overflow con '1 << n'? –

+0

@LuchianGrigore Sort of. è necessario aggiungere il nome della variabile all'istruzione o, ma se si dimentica di farlo, allora no. Questo è solo un modo più conciso per verificare se si tratta di un insieme di tre valori. E sì, potrebbe traboccare, a seconda delle dimensioni dei numeri interi sulla macchina per cui stavi sviluppando. Tuttavia, secondo la mia esperienza, è raro avere a che fare con più di 32 valori diversi in un enum, che è una buona stima del massimo che si avrebbe. –

0

Non può anche fare qualcosa di simile

enum myEnum {typeA,typeB, typeC}; 

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

Esiste la possibilità che il compilatore ottimizzi i controlli? Se viene aggiunto un * LastType *, allora verifica che 'arg1 dashesy

0

Purtroppo non c'è un modo semplice per farlo livello linguistico (almeno con C), devi solo fare in modo che si sta utilizzando solo le variabili definito tramite enum.

Anche se è possibile attivare uno dei seguenti avvisi del compilatore insieme -Werror:

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

Questo rende accumulo fallire se una delle enumerazioni è mancato interruttore interno.

0

enumerazioni in C++ già avere tipi più forti in C.

Prendere il seguente programma semplice:

#include <iostream> 

enum E 
{ 
    A, 
    B 
}; 

void f(E e) 
{ 
} 

int main() 
{ 
    f(1); 
} 

Utilizzando il compilatore GCC otterrò un questo errore:

 
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)’ 

Quindi, come puoi vedere, i membri dell'enumerazione sono già stati controllati.

Se si vuole ancora più forte controllo dei tipi, e hanno un C++ 11 compilatore in grado, è possibile utilizzare anche più forte tipo di controllo per le enumerazioni, vedi http://en.wikipedia.org/wiki/C%2B%2B11#Strongly_typed_enumerations.

+0

Cosa c'è 'e'? –

+1

@LightnessRacesinOrbit Non ho davvero idea di cosa dovrebbe essere, la mia memoria è un po 'confusa dopo quasi quattro anni ... :) È * probabilmente * supposto un letterale intero. –

1

Un trucco che ho usato in passato:

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

e quindi controllare per vedere se il valore è > FIRST_FOO && < LAST_FOO .

Ovviamente, ciò presuppone che non vi siano intervalli tra i valori di enumerazione.

Altrimenti no, non esiste un metodo valido per fare ciò che stai chiedendo (almeno in C).


Dalle ultime linea 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.
Problemi correlati