Добавление предопределенных данных для перечислений typedef в C

StackOverflow https://stackoverflow.com/questions/35973

  •  09-06-2019
  •  | 
  •  

Вопрос

Каков наилучший подход к определению дополнительных данных для перечислений typedef в C?

Пример:

typedef enum {
  kVizsla = 0,
  kTerrier = 3,
  kYellowLab = 10
} DogType;

Теперь я хотел бы определить имена для каждого из них, например kVizsla должно быть "визсла".В настоящее время я использую функцию, которая возвращает строку, используя большой блок переключения.

Это было полезно?

Решение

@dmckee:Я думаю, что предложенное решение хорошее, но для простых данных (напримересли нужно только имя), оно может быть дополнено автоматически сгенерированным кодом.Хотя существует множество способов автоматической генерации кода, для чего-то столь простого, как этот, я полагаю, вы могли бы написать простой XSLT, который принимает XML-представление перечисления и выводит файл кода.

XML-файл будет иметь вид:

<EnumsDefinition>
    <Enum name="DogType">
        <Value name="Vizsla" value="0" />
        <Value name="Terrier" value="3" />
        <Value name="YellowLab" value="10" />
    </Enum>
</EnumsDefinition>

и результирующий код был бы чем-то похож на то, что dmckee предложил в своем решении.

Для получения информации о том, как написать такой XSLT, попробуйте здесь или просто найдите это в Google и найдите подходящий учебник.Писать XSLT не очень весело, IMO, но и не так уж плохо, по крайней мере, для относительно простых задач, подобных этой.

Другие советы

Идеально подходит для X () макросы. Полем Эти типы макросов могут использовать препроцессор C для построения перечислений и массивов из того же источника. Вам нужно только добавить новые данные в макрос #define, содержащий X ().

Ваш пример может быть написан следующим образом:

// All dog data goes in this list
#define XDOGTYPE \
  X(kVizsla,0,"vizsla") \
  X(kTerrier,3,"terrier") \
  X(kYellowLab,10,"yellowlab")

 // Dog info
 typedef struct {
     int val;       // Defined value
     char * desc;   // Text description
 } DogType;

 // Build an array index using the Names
 typedef enum {
  #define X(Name,Val,Text)     Name,
   XDOGTYPE
  #undef X
  MAXDOGS
 } DogIndex;

 // Build a lookup table of values
 DogType Dog[] = {
  #define X(Name,Val,Text)    {Val,Text},
   XDOGTYPE
  #undef X
 };

 // Access the values
 for (i=0; i < MAXDOGS; i++)
    printf("%d: %s\n",Dog[i].val,Dog[i].desc);

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

char *DogList[] = {
  "vizsla", /* element 0 */
  NULL,
  NULL,
  NULL,
  "terrier", /* element 3 */
  ...
};

Это неэффективно для разреженных перечислений.

Даже если перечисление не является плотным, вы можете использовать массив структур для удержания отображения.

typedef struct DogMaps {
  DogType index;
  char * name;
} DogMapt;
DogMapt DogMap[] = {
  {kVizsla, "vizsla"},
  {kTerrier, "terrier"},
  {kYellowLab, "yellow lab"},
  NULL
};

Второй подход очень гибкий, но это означает поиск через картирование каждый раз, когда вам нужно использовать данные. Для больших наборов данных рассмотрим B-три или хэш вместо массива.

Любой метод может быть обобщен для подключения дополнительных данных. В первом использовании массива структур, во втором, просто добавьте больше членов в структуру.

Вы, конечно, хотите написать различные обработчики, чтобы упростить ваше взаимодействие с этими структурами данных.


@Hersshi во что бы то ни стало, отдельный код и данные. Приведенные выше примеры должны быть четкими, а не функциональными.

Я краснею, чтобы признать, что для этой цели все еще использую отдельные плоские файлы, а не тот тип структурированного ввода, который вы демонстрируете, но мой производственный код будет читать как можно больше данных из внешних источников.


Подождите, я вижу, что вы имеете в виду генерацию кода.

Конечно. В этом нет ничего плохого.

Я подозреваю, что однако, что OP интересовался тем, как должен выглядеть сгенерированный код ...

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top