Как проверить, действительна ли переменная enum?
У меня есть перечисление:
enum myenum{
typeA,
typeB,
typeC
} myenum_t;
Затем функции должны вызываться с параметром enum:
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
не кажется таким изящным.
Есть ли лучший способ проверить, является ли перечисление действительным или нет?
Ответы
Ответ 1
Общим соглашением для этого является сделать что-то вроде этого:
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
автоматически обновляется, и ваш код проверки ошибок не нуждается в изменении.
Ответ 2
Вы можете использовать побитовое перечисление:
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");
Это, конечно, предполагает, что вы не задаете ручные значения для вашего перечисления, что довольно редко, если не использовать побитовые перечисления.
Ответ 3
Да.
Пусть компилятор выполнит свою работу, не применяйте int
к типу enum
, и вам должно быть хорошо.
Ответ 4
Один трюк, который я использовал в прошлом:
enum foo {FIRST_FOO, BAR, BLETCH, BLURGA, BLAH, LAST_FOO};
а затем проверьте, соответствует ли ваше значение > FIRST_FOO && < LAST_FOO
1.
Конечно, это предполагает, что между вашими значениями перечисления нет пробелов.
В противном случае нет, нет хорошего способа делать то, что вы просите (по крайней мере, на C).
1 Из последнего онлайн C Language Standard:
6.7.2.2 Спецификаторы перечисления
...
3 Идентификаторы в списке перечислителей объявляются как константы, имеющие тип int
и
может появляться везде, где это разрешено. 109) Перечислитель с =
определяет его
константа перечисления как значение постоянного выражения. Если первый счетчик
no =
, значение его константы перечисления 0
. Каждый последующий перечислитель без =
определяет его константу перечисления как значение константного выражения, полученного
добавив 1
к значению предыдущей константы перечисления. (Использование счетчиков с
=
может создавать константы перечисления со значениями, которые дублируют другие значения в одном и том же
перечисление.) Перечисления перечисления также известны как его члены.
Ответ 5
Разве вы не можете сделать что-то вроде
enum myEnum {typeA,typeB, typeC};
int myFunction (myEnum arg1) {
if (arg1 >= typeA && arg1 <= typeC) {
// do work here
} else {
printf("invalid argument!");
}
return 0;
}
Ответ 6
К сожалению, нет простого способа сделать это на уровне языка (по крайней мере, с C
), вам просто нужно убедиться, что вы используете только переменные, определенные с помощью enum
.
Хотя вы можете включить одно из следующих предупреждений компилятора вместе с -Werror
:
-
-Wswitch
-
-Wswitch-default
-
-Wswitch-enum
Это приводит к сбою сборки, если одно из перечислений пропущено внутри коммутатора.
Ответ 7
Перечисления в С++ уже имеют более сильные типы, чем в 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)’
Итак, как вы видите, элементы перечисления уже проверены.
Если вы хотите еще более сильную проверку типов и иметь компилятор С++ 11, вы можете использовать еще более эффективную проверку типов для перечислений, см. http://en.wikipedia.org/wiki/C%2B%2B11#Strongly_typed_enumerations.