在C中为typedef枚举添加预定义数据

时间:2020-03-05 18:45:26  来源:igfitidea点击:

为C中的typedef枚举定义其他数据的最佳方法是什么?

例子:

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

现在,我想为每个名称定义名称,例如," kVizsla"应为" vizsla"。
我目前使用一个使用大开关块返回字符串的函数。

解决方案

回答

这是一个开放式的问题,但是一个建议是使用以枚举为键类型并在值中包含额外信息的映射。 (与示例不同,如果索引是连续的,则可以使用序列容器而不是映射)。

回答

如果枚举值足够密集,则可以定义一个数组来保存字符串并仅对其进行查找(对于任何跳过的值,请使用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树或者哈希而不是数组。

可以将这两种方法通用化以连接更多数据。第一种使用结构数组,第二种使用结构中添加更多成员。

当然,我们将需要编写各种处理程序来简化与这些数据结构的交互。

@Hershi一定要分开代码和数据。以上示例是为了清楚而不是功能。

我很脸红,承认我仍然为此目的使用空格分隔的平面文件,而不是我们展示的结构化输入,但是我的生产代码将尽可能多地从外部源读取数据。

等等,我看到意思是代码生成。

当然。没有错。

我怀疑,尽管OP对生成的代码应该是什么样的感兴趣...

回答

@dmckee:我认为建议的解决方案很好,但是对于简单数据(例如,仅需要名称),可以使用自动生成的代码进行扩充。尽管有很多方法可以自动生成代码,但是对于如此简单的事情,我相信我们可以编写一个简单的XSLT,该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预处理器从同一源构造枚举和数组。我们只需要向包含X()宏的#define中添加新数据即可。

示例可以编写如下:

// 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);