Pregunta

¿Cuál es el mejor enfoque para definir datos adicionales para enumeraciones typedef en C?

Ejemplo:

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

Ahora me gustaría definir nombres para cada uno, por ejemplo kVizsla debería ser "vizsla".Actualmente uso una función que devuelve una cadena usando un bloque de interruptor grande.

¿Fue útil?

Solución

@dmckee:Creo que la solución sugerida es buena, pero para datos simples (p. ej.si solo se necesita el nombre) se podría aumentar con código generado automáticamente.Si bien hay muchas formas de generar código automáticamente, para algo tan simple como esto creo que se podría escribir un XSLT simple que tome una representación XML de la enumeración y genere el archivo de código.

El XML tendría la forma:

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

y el código resultante sería algo similar a lo que sugirió dmckee en su solución.

Para obtener información sobre cómo escribir un XSLT de este tipo, intente aquí o simplemente búsquelo en Google y encuentre un tutorial que se ajuste.En mi opinión, escribir XSLT no es muy divertido, pero tampoco es tan malo, al menos para tareas relativamente simples como estas.

Otros consejos

Un ajuste perfecto para Macros X().Estos tipos de macros pueden usar el preprocesador de C para construir enumeraciones y matrices a partir de la misma fuente.Solo necesita agregar nuevos datos al #define que contiene la macro X().

Su ejemplo se puede escribir de la siguiente manera:

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

Si sus valores enumerados son lo suficientemente densos, puede definir una matriz para contener las cadenas y simplemente buscarlas (use NULL para cualquier valor omitido y agregue un controlador de casos especial en su rutina de búsqueda).

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

Esto es ineficiente para enumeraciones escasas.

Incluso si la enumeración no es densa, puede utilizar una serie de estructuras para realizar el mapeo.

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

El segundo enfoque es muy flexible, pero implica una búsqueda en el mapeo cada vez que necesite utilizar los datos.Para conjuntos de datos grandes, considere un árbol b o un hash en lugar de una matriz.

Cualquiera de los métodos se puede generalizar para conectar más datos.En el primero use una matriz de estructuras, en el segundo simplemente agregue más miembros a la estructura.

Por supuesto, querrás escribir varios controladores para simplificar tu interacción con estas estructuras de datos.


@Hershi Por supuesto, separe el código y los datos.Los ejemplos anteriores pretenden ser más claros que funcionales.

Me sonroja admitir que todavía uso archivos planos separados por espacios en blanco para ese propósito, en lugar del tipo de entrada estructurada que exhibes, pero mi código de producción leería la mayor cantidad posible de datos de fuentes externas.


Espera, veo que te refieres a la generación de código.

Seguro.Nada de malo con eso.

Sin embargo, sospecho que el OP estaba interesado en cómo debería verse el código generado...

Esa es una pregunta abierta, pero una sugerencia sería usar un mapa con la enumeración como tipo de clave y la información adicional en el valor.(Si sus índices son continuos, a diferencia del ejemplo, puede usar un contenedor de secuencia en lugar de un mapa).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top