Получить имя enum, связанное с int val в C. Избегайте typecast от int до enum - PullRequest
0 голосов
/ 04 декабря 2018

Как мне получить имя enum, связанное с int val.

У меня есть следующий код:

   #include<stdio.h>
   #include<stdlib.h>


   typedef enum _MyID{
      id1 = 1,
      id2 = 2,
      id3 = 3,
   }MyID;

  MyID get_idname(int id_val)
  {
      switch(id_val){
         case 1:
            return id1;
         case 2:
            return id2;
         case 3:
            return id3;
         default:  //checks for invalid ID
            return -1;
      }
  }

   int main()
   {
       int val1 = 1;
       int val2 = 2;
       MyID new_id1 = (MyID)(val1|val2);
       MyID new_id2 = (MyID)(4);
       MyID new_id3 = get_idname(3);
       MyID new_id4 = get_idname(4);
       printf("id is new_id1 %d, new_id2 %d, new_id3 %d, new_id4 %d \n", new_id1, new_id2, new_id3, new_id4);

       return 0;
   }

Приведенный выше код выводит следующее: id is new_id1 3, new_id2 4, new_id3 3, new_id4 -1

Ясно, приведение типовint to enum опасен.Одним из способов решения этой проблемы является использование функции (как в предыдущем примере) с оператором switch, чтобы перехватить переданное недопустимое значение.Проблема в том, что у меня действительно большое перечисление с сотнями значений, поэтому написание регистра переключателей для каждого перечисления является сложной задачей, а не масштабируемым подходом.Я хотел бы знать, есть ли какое-либо эффективное решение для того же самого.

Ответы [ 2 ]

0 голосов
/ 04 декабря 2018

Глобальные символы, начинающиеся с подчеркивания, и особенно символы подчеркивания + заглавные буквы и начала, зарезервированы.Если у вас есть и тег, и typedef, просто выполните typedef MyID { ...} MyID;.

Что касается вашей проблемы, если константы enum непрерывно увеличиваются, вы можете просто сделать:

typedef enum MyID{
      idERR=-1,
      id1 = 1,
      id2 = 2,
      id3 = 3,
      //...
      idMAX
}MyID;
MyID get_idname(int id_val) { return (id_val>0&&id_val<idMAX)?id_val:-1; }

Кроме этого всегда есть генерация кода.(Если написание программы утомительно, напишите программу для написания программы).

Если вы намереваетесь присвоить -1 в enum, вам, вероятно, следует также сделать константу перечислителя для нее.В противном случае компилятор может сделать MyID типом без знака, что может привести к неприятному сюрпризу, если вы когда-либо выполните if (0>my_id).

0 голосов
/ 04 декабря 2018

Если перечисления имен являются шаблонными (как в вашем примере), вы можете использовать макрос для быстрого заполнения регистра.Например, 101 случай может быть просто заполнен

#define CASE(N) case N: return id##N;
#define DOZEN_CASES(N) CASE(N##0) CASE(N##1) CASE(N##2) CASE(N##3) CASE(N##4) CASE(N##5)\
 CASE(N##6) CASE(N##7) CASE(N##8) CASE(N##9)

MyID get_idname(int id_val)
{
   switch (id_val) {
      DOZEN_CASES() DOZEN_CASES(1)
      DOZEN_CASES(2) DOZEN_CASES(3)
      DOZEN_CASES(4) DOZEN_CASES(5)
      DOZEN_CASES(6) DOZEN_CASES(7)
      DOZEN_CASES(8) DOZEN_CASES(9)
      CASE(100) CASE(101)
   default:  //checks for invalid ID
      return -1;
   }
}
...