2012-02-06 35 views
12

Tôi có một enum:Làm cách nào để kiểm tra xem biến enum có hợp lệ không?

enum myenum{ 
    typeA, 
    typeB, 
    typeC 
} myenum_t; 

Sau đó, một chức năng là để được gọi với một tham số enum:

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

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

Nhưng, như myenum_t phát triển với ngày càng nhiều giá trị, myfunction dường như không thật thanh lịch.

Có cách nào tốt hơn để kiểm tra xem liệu enum có hợp lệ hay không?

+0

Không có một bản sao của tiêu chuẩn, tôi sẽ được trích xuất để nói điều này mà không cần trích dẫn nó, vì vậy tôi sẽ làm cho nó một lời nhận xét: Trong mỗi lần thực hiện C hoặc C++ tôi đã thấy, các giá trị 'enum' được phân bổ theo thứ tự số tăng dần. Vì vậy, tất cả những gì bạn cần làm là thêm 'firstEnum = typeA, lastEnum = typeC' vào' enum' và sau đó kiểm tra phạm vi bằng 'if (int (inputEnum) int (lastEnum)) {/ * xử lý lỗi * /} '. –

Trả lời

18

Một quy ước chung cho việc này là để làm một cái gì đó như thế này:

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

Sau đó, bạn có thể kiểm tra (t < num_types).

Nếu sau đó bạn thêm nhiều enums, ví dụ:

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

sau đó num_types được cập nhật tự động và mã kiểm tra lỗi của bạn không cần thay đổi.

+0

'myenum_t' có nghĩa là gì sau khai báo enum của bạn? [Tham chiếu C#] (http://msdn.microsoft.com/en-us/library/sbbt4032.aspx) dường như không đề cập đến nó; không có ví dụ nào của họ có bất cứ thứ gì sau cú đúp đóng. –

+0

@PatrickM nó là cần thiết trong C nhưng không phải trong C + + hoặc C# do thực tế là trong C bạn không thể sử dụng một thẻ enum như một loại. Tuy nhiên để có ý nghĩa trong câu trả lời ở trên, tôi mong đợi để thấy từ khóa 'typedef' trước từ khóa' enum', khai báo 'myenum_t' là cùng kiểu với' enum myenum'. –

+0

Nếu enum là công khai phải đối mặt, sau đó bạn đang vạch trần num_types với thế giới. Có đường nào quanh đó không? – duhanebel

3

Có.

Để trình biên dịch thực hiện công việc của mình, không được đúc int thành loại enum và bạn sẽ tốt.

+0

nhưng đôi khi chúng ta cần phải đúc –

5

Bạn có thể sử dụng một enum Bitwise:

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

Xin lỗi, có vẻ như tôi đã đọc các câu hỏi sai.

Có vẻ như những gì bạn muốn làm là xác định xem bạn có một giá trị thích hợp được chuyển vào không, không phải tùy chọn ngẫu nhiên không hợp lệ. Trong trường hợp đó, tùy chọn hợp lý nhất là thế này:

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

Đây là, tất nhiên, giả sử bạn không đặt giá trị của nhãn hiệu cho enum của bạn, trong đó, là khá hiếm trừ khi sử dụng enums Bitwise.

+0

Tính năng này có hoạt động nếu nhiều giá trị được thêm vào enum không? –

+3

"Nhưng, như myenum_t phát triển với giá trị ngày càng nhiều". Không phải là có cơ hội tràn với '1 << n'? –

+0

@LuchianGrigore Sắp xếp. bạn phải thêm tên biến vào câu lệnh hoặc câu lệnh, nhưng nếu bạn quên làm điều đó, thì không. Đây chỉ là cách kiểm tra ngắn gọn hơn nếu nó là một bộ ba giá trị. Và có, nó có thể tràn, tùy thuộc vào kích thước nguyên trên máy bạn đang phát triển. Tuy nhiên, theo kinh nghiệm của tôi, hiếm khi phải đối phó với hơn 32 giá trị khác nhau trong một enum, đó là một ước tính tốt về mức tối đa bạn sẽ có. –

0

Không thể bạn cũng làm một cái gì đó giống như

enum myEnum {typeA,typeB, typeC}; 

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

Có khả năng trình biên dịch tối ưu hóa các kiểm tra không? Nếu một * LastType * được thêm vào sau đó kiểm tra 'arg1 dashesy

0

Đáng tiếc là không có một cách đơn giản để làm điều đó mức độ ngôn ngữ (ít nhất là với C), bạn chỉ cần phải chắc chắn rằng bạn đang sử dụng chỉ biến được xác định qua enum.

Mặc dù bạn có thể cho phép một trong những cảnh báo trình biên dịch sau cùng với -Werror:

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

này làm cho việc xây dựng thất bại nếu một trong những sự đếm được bỏ qua bên trong chuyển đổi.

0

Enumerations trong C++ đã có các loại mạnh hơn trong C.

Lấy chương trình đơn giản sau đây:

#include <iostream> 

enum E 
{ 
    A, 
    B 
}; 

void f(E e) 
{ 
} 

int main() 
{ 
    f(1); 
} 

Sử dụng trình biên dịch GCC tôi sẽ nhận được một lỗi này:

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

Vì vậy, như bạn có thể thấy các thành viên điều tra đã được kiểm tra.

Nếu bạn muốn kiểm tra kiểu mạnh hơn, và có trình biên dịch có khả năng C++ 11, bạn có thể sử dụng kiểm tra kiểu mạnh hơn cho enums, xem http://en.wikipedia.org/wiki/C%2B%2B11#Strongly_typed_enumerations.

+0

Điều gì là 'e'? –

+1

@LightnessRacesinOrbit Tôi thực sự không biết nó là gì, bộ nhớ của tôi hơi mơ hồ sau gần bốn năm ... :) Đó là * có lẽ * được cho là một số nguyên. –

1

Một mẹo nhỏ tôi đã sử dụng trong quá khứ:

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

và sau đó kiểm tra xem giá trị của bạn là > FIRST_FOO && < LAST_FOO .

Tất nhiên, điều này giả định rằng không có khoảng trống giữa các giá trị liệt kê của bạn.

Nếu không, không, không có phương pháp tốt để làm những gì bạn đang yêu cầu (ít nhất là trong C).


Từ trực tuyến mới nhất 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.
Các vấn đề liên quan