2012-02-06 19 views
12

Mam ENUM:Jak sprawdzić, czy zmienna wyliczeniowa jest ważna?

enum myenum{ 
    typeA, 
    typeB, 
    typeC 
} myenum_t; 

Następnie funkcje ma być wywołana z parametrem ENUM:

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

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

Ale, jak myenum_t rośnie wraz z coraz większej wartości, nie wydaje myfunction taki elegancki.

Czy istnieje lepszy sposób sprawdzenia, czy wyliczenie jest poprawne, czy nie?

+0

Nie mając kopię standardzie, bym się oszukany przez mówiąc to bez cytowania, więc zrobię to komentarz: W każda implementacja C lub C++ widziałem, wartości 'enum' są przydzielane w rosnącej kolejności numerycznej. Więc wszystko, co musisz zrobić, to dodać 'firstEnum = typeA, lastEnum = typeC' do twojego' enum', a następnie sprawdzić zakres z 'if (int (inputEnum) int (lastEnum)) {/ * błąd obsługi * /} '. –

Odpowiedz

18

Wspólna konwencja jest to, aby zrobić coś takiego:

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

Następnie można sprawdzić (t < num_types).

Jeśli następnie dodasz więcej wyliczeń, np.

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

następnie num_types jest automatycznie aktualizowana i twój błąd sprawdzania kodu nie trzeba zmieniać.

+0

Co oznacza 'myenum_t' po deklaracji wyliczeniowej? Odnośnik [C# Reference] (http://msdn.microsoft.com/en-us/library/sbbt4032.aspx) nie wspomina o tym; żaden z ich przykładów nie ma nic po nawiasie zamykającym. –

+0

@PatrickM jest wymagany w języku C, ale nie w C++ lub C#, ponieważ w C nie można użyć znacznika enum jako typu. Jednakże, aby uzyskać sens w powyższej odpowiedzi, spodziewam się zobaczyć słowo kluczowe 'typedef' przed słowem kluczowym' enum', określające, że 'myenum_t' jest tego samego typu co' enum myenum'. –

+0

Jeśli to wyliczenie jest publiczne, to ujawniasz num_types światu. Czy istnieje jakiś sposób? – duhanebel

3

Tak.

Pozwól, aby kompilator wykonał swoją pracę, nie używaj od int typu enum i powinieneś być dobry.

+0

, ale czasami musimy odrzucić –

5

Można użyć enum bitowe:

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

wybaczcie, wydaje Czytałem kwestia źle.

Wygląda na to, że chcesz określić, czy masz przekazaną prawidłową wartość, a nie jakąś losową niepoprawną opcję. W tym przypadku najbardziej logicznym rozwiązaniem jest to:

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

Jest to, oczywiście, zakładając, że nie ustawić wartości dla wyliczenia manualnych, co jest dość rzadkie, chyba że przy użyciu bitowe teksty stałe.

+0

Czy to działa, jeśli do wyliczenia zostało dodanych więcej wartości? –

+3

"Ale, jak myenum_t rośnie z coraz większą liczbą wartości". Czy nie ma szansy przepełnienia z '1 << n'? –

+0

@LuchianGrigore Sortuj. musisz dodać nazwę zmiennej do instrukcji lub, ale jeśli zapomnisz to zrobić, to nie. Jest to po prostu bardziej zwięzły sposób sprawdzenia, czy jest to zestaw trzech wartości. I tak, może się przepełnić, w zależności od wielkości całkowitej na maszynie, dla której pracujesz. Jednak z mojego doświadczenia wynika, że ​​rzadko trzeba radzić sobie z ponad 32 różnymi wartościami w wyliczeniu, co jest dobrym oszacowaniem maksymalnego poziomu. –

0

nie można też zrobić coś podobnego

enum myEnum {typeA,typeB, typeC}; 

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

Czy istnieje szansa, że ​​kompilator optymalizuje sprawdzanie? Jeśli dodany jest * LastType *, sprawdź, czy 'arg1 dashesy

0

Niestety nie jest prostym sposobem na to poziom języka (przynajmniej z C), po prostu trzeba się upewnić, że używasz tylko zmienne zdefiniowane przez enum.

Chociaż można włączyć jedną z następujących ostrzeżeń kompilatora wraz z -Werror:

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

To sprawia build powiedzie się, jeśli jeden z teksty stałe pominięcia wewnątrz przełącznika.

0

Wyliczenia w C++ mają już silniejsze typy niż w C.

Weźmy następujący prosty program:

#include <iostream> 

enum E 
{ 
    A, 
    B 
}; 

void f(E e) 
{ 
} 

int main() 
{ 
    f(1); 
} 

Korzystanie z kompilatora GCC będzie dostaję ten błąd:

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

Tak więc, jak widać, elementy wyliczeniowe są już sprawdzone.

Jeśli chcesz jeszcze silniej sprawdzać typ i mieć kompilator obsługujący C++ 11, możesz użyć jeszcze silniejszego sprawdzania typów dla wyliczeń, zobacz http://en.wikipedia.org/wiki/C%2B%2B11#Strongly_typed_enumerations.

+0

Co to jest 'e'? –

+1

@LightnessRacesinOrbit Naprawdę nie mam pojęcia, co to ma być, moja pamięć jest nieco mglista po prawie czterech latach ... :) Jest to * prawdopodobnie * przypuszczalnie liczba całkowita. –

1

Jeden trick Użyłem w przeszłości:

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

a następnie sprawdzić, czy wartość jest > FIRST_FOO && < LAST_FOO .

Oczywiście zakłada to, że między wartościami wyliczeniowymi nie ma żadnych przerw.

W przeciwnym razie nie, nie ma dobrej metody robienia tego, o co prosisz (przynajmniej w C).


Z odświerzyć 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.
Powiązane problemy