2012-02-06 180 views
12

我有一个枚举:如何检查一个枚举变量是否有效?

enum myenum{ 
    typeA, 
    typeB, 
    typeC 
} myenum_t; 

然后,功能是用一个枚举参数来调用:

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

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

但是,正如myenum_t增长随着越来越多的价值,myfunction似乎并不如此优雅。

有没有更好的方法来检查一个枚举是否有效?

+0

不具有标准的副本,我就会撕开这么说,没有引用它,所以我会让它评论:在我看到每个C或C++实现,'enum'值都是按递增的数字顺序分配的。所以你所要做的就是在'enum'中加入'firstEnum = typeA,lastEnum = typeC',然后用'if(int(inputEnum) int(lastEnum) ){/ *处理错误* /}'。 – 2012-02-06 14:49:51

回答

18

一个常见的约定是做这样的事情:

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

然后你可以检查(t < num_types)

如果随后添加更多枚举,例如

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

然后num_types会自动更新并且您的错误检查代码无需更改。

+0

你的枚举声明后'myenum_t'是什么意思? [C#参考](http://msdn.microsoft.com/en-us/library/sbbt4032.aspx)似乎没有提及它;在大括号之后,他们的例子都没有任何东西。 – 2013-08-12 17:02:44

+0

@PatrickM它在C中是必需的,但在C++或C#中不需要,因为在C中不能使用枚举标记作为类型。然而,在上面的答案中,我希望在'enum'关键字之前看到'typedef'关键字,并声明'myenum_t'与'enum myenum'是同一类型。 – 2013-11-15 18:27:47

+0

如果这个枚举是公开的,那么你将num_types公开给这个世界。有没有办法解决这个问题? – duhanebel 2015-05-06 14:14:06

3

是的。

让编译器完成它的工作,不要将int转换为enum类型,你应该很好。

+0

但有时我们需要投入 – 2016-09-15 14:20:55

5

你可以使用按位枚举:

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

打扰我,似乎我已阅读题做错。

看来你想要做的是确定你是否有适当的值传入,而不是一些随机无效的选项。在这种情况下,最合理的选择是这样的:

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

这是当然,假设你不为你的枚举,这是除非使用逐枚举相当罕见设置手动值。

+0

如果将更多值添加到枚举中,这是否工作? – 2012-02-06 14:52:18

+3

“但是,随着myenum_t越来越多的价值增长”。是不是有'1 << n'溢出的机会? – 2012-02-06 14:54:39

+0

@LuchianGrigore的排序。您必须将变量名称添加到or语句,但是如果您忘记这么做,那么不会。这只是一个更简洁的方式来检查它是否是一组三个值。是的,它可能会溢出,取决于您正在开发的机器上的整数大小。然而,根据我的经验,在一个枚举中处理超过32个不同的值是很少见的,这是对你所能达到的最大值的一个很好的估计。 – 2012-02-06 14:56:41

0

你能不能也这样做

enum myEnum {typeA,typeB, typeC}; 

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

编译器是否有机会优化检查?如果添加* LastType *,那么检查'arg1 dashesy 2012-07-13 18:33:16

0

不幸的是,没有一个简单的方法来做到这一点的语言水平(至少C),你只需要确保你只使用变量通过enum定义。

虽然你可以用-Werror启用以下编译器警告之一在一起:如果枚举中的一个被错过

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

这使得构建失败内部开关。

0

枚举在C++已经具有较强的类型比C.

采取以下简单的程序:

#include <iostream> 

enum E 
{ 
    A, 
    B 
}; 

void f(E e) 
{ 
} 

int main() 
{ 
    f(1); 
} 

使用GCC编译器,我会得到这个错误:

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

所以你可以看到枚举成员已经被检查过。

如果您想要更强大的类型检查,并且具有支持C++ 11的编译器,则可以使用更强大的类型检查枚举,请参阅http://en.wikipedia.org/wiki/C%2B%2B11#Strongly_typed_enumerations

+0

什么是'e'? – 2015-12-01 15:18:11

+1

@LightnessRacesinOrbit我真的不知道它应该是什么,我的记忆几乎四年后有点朦胧...... :)它可能*被认为是一个整数字面量。 – 2015-12-01 15:25:17

1

一招我在过去使用:

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

,然后检查,看看你的价值> FIRST_FOO && < LAST_FOO

当然,这假定您的枚举值之间没有差距。

否则,不,没有什么好的方法来做你要求的东西(至少在C中)。


从最新的在线 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.