Add predefined data for typedef enumerations in C

What is the best approach for defining additional data for typedef enumerations in C?

Example:

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

Now I would like to define names for each, for example kVizsla should be "vizsla". I am currently using a function that returns a string using a large block of radio buttons.

+4
source share
4 answers

@dmckee: I think the proposed solution is good, but for simple data (for example, if only a name is required) it can be supplemented with automatically generated code. Although there are many ways to automatically generate code, for something as simple as I assume you could write a simple XSLT that takes an XML representation of the enumeration and outputs a code file.

XML will look like:

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

and the resulting code will be something similar to what dmckee suggested in its solution.

For information on how to write such an XSLT, try here or just do a google search and find a tutorial that works. Writing XSLT is not a lot of fun IMO, but it's not so bad, at least for relatively simple tasks like these.

+2
source

Ideal for X () macros . These types of macros can use the C preprocessor to create enumerations and arrays from a single source. You only need to add new data to #define containing the X () macro.

Your example can be written as follows:

 // 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); 
+3
source

If your listed values ​​are dense enough, you can define an array to store the strings and just view them (use NULL for any missing value and add a special case handler to your search procedure).

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

This is inefficient for sparse enumerations.

Even if the enumeration is not dense, you can use an array of structures to store the display.

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

The second approach is very flexible, but that means searching through matching every time you need to use data. For large datasets, consider a b-tree or hash instead of an array.

Any method can be generalized to connect more data. In the first case, use an array of structures, in the second just add more members to the structure.

Of course, you will want to write various handlers to simplify your interaction with these data structures.


@Hershi Anyway, separate code and data. The above examples should be clear, not functional.

I am blushing to admit that for this purpose I still use separate separated spaces, not the type of structured input that you show, but my production code will read as much data as possible from external sources.


Wait, I see what you mean by code generation.

Sure. Nothing wrong with that.

I suspect the OP was interested in how the generated code should look ...

+1
source

Such an open question, but one suggestion is to use a card with an enumeration as a key type and additional information in the value. (If your indexes are continuous, unlike the example, you can use a sequence container instead of a map).

0
source

Source: https://habr.com/ru/post/1276492/


All Articles