2009-04-03 12 views
35

En C, ¿hay una buena manera de rastrear la cantidad de elementos en una enumeración? He vistoNúmero de elementos en una enumeración

enum blah { 
    FIRST, 
    SECOND, 
    THIRD, 
    LAST 
}; 

Pero esto solo funciona si los elementos son secuenciales y comienzan en cero.

+0

Consulte la pregunta sobre ['enum' en C++ como' enum' en Ada] (http: // stackoverflow.com/questions/300592/enum-in-c-like-enum-in-ada). –

Respuesta

32

No creo que exista. Pero, ¿qué harías con tal número si no son secuenciales, y aún no tienes una lista de ellos en algún lugar? Y si ellos son secuenciales, pero comienzan a partir de un número diferente, siempre se puede hacer:

enum blah { 
    FIRST = 128, 
    SECOND, 
    THIRD, 
    END 
}; 
const int blah_count = END - FIRST; 
+0

¿pueden los tipos enum ser negativos? Si es así, ten cuidado con este. – ojblass

+0

FIRST = -2 aún calculó correctamente, creo: 1 - (-2) = 3. – paxdiablo

+2

No hay que tener cuidado; la resta funciona bien para números negativos. Pax tiene razón. –

6

Lamentablemente, no. No hay.

3

Bueno, ya que las enumeraciones no pueden cambiar en tiempo de ejecución, lo mejor que puede hacer es:

enum blah { 
    FIRST = 7, 
    SECOND = 15, 
    THIRD = 9, 
    LAST = 12 
}; 
#define blahcount 4 /* counted manually, keep these in sync */ 

Pero me resulta difícil imaginar una situación en la que esa información sería útil. ¿Qué estás tratando de hacer exactamente?

+1

Sí, ¿por qué querrías hacer eso? – ojblass

+2

Tengo una situación en la que quiero asignar aleatoriamente valores enum a una matriz. Necesito saber cuántos valores diferentes hay para poder obtener el rango correcto. – anthropomorphic

2
int enaumVals[] = 
{ 
FIRST, 
SECOND, 
THIRD, 
LAST 
}; 

#define NUM_ENUMS sizeof(enaumVals)/sizeof (int); 
+7

Esto parece requerir la repetición de toda la enumeración en una matriz, simplemente para permitir el uso de sizeof: me parece más esfuerzo que el de #definir COUNT 4 –

+1

En C el tamaño se calcula en tiempo de compilación. C no es un lenguaje interpretado, este método es tan eficiente como usar una definición de arreglo y simplifica el mantenimiento. – Fulup

55

Si no asigna sus enumeraciones que se pueden hacer algunas cosas como esta:

enum MyType { 
    Type1, 
    Type2, 
    Type3, 
    NumberOfTypes 
} 

NumberOfTypes evaluarán a 3, que es el número de tipos reales.

+2

¡Buen truco! claramente el más fácil para enum secuencial –

+1

¿Se puede estar seguro de que en cada implementación de C en cualquier lugar en todo momento las enumeraciones comienzan desde 0? Supongo que sí, pero ¿siempre es verdad? – JohnyTex

17

Vieja pregunta, lo sé. Esto es para los googlers con la misma pregunta.

Usted podría utilizar X-Macros

Ejemplo:

//The values are defined via a map which calls a given macro which is defined later 
#define ENUM_MAP(X) \ 
     X(VALA, 0) \ 
     X(VALB, 10) \ 
     X(VALC, 20) 

//Using the map for the enum decl 
#define X(n, v) [n] = v, 
typedef enum val_list { 
    ENUM_MAP(X) //results in [VALA] = 0, etc... 
} val_list; 
#undef X 

//For the count of values 
#define X(n, v) + 1 
int val_list_count = 0 + ENUM_MAP(X); //evaluates to 0 + 1 + 1 + 1 
#undef X 

Esto también es transparente para un IDE, por lo que se completa automáticamente funciona bien (como todo se hace en el pre-procesador).

+1

Impresionante, en realidad vine aquí porque estaba buscando una buena manera de determinar el _número_ de elementos en un X_MACRO, y esta es una buena manera. – BeeOnRope

+0

También podría tomar el número de elementos en la matriz 'val_list' utilizando el idiomatic' (sizeof val_list/sizeof val_list [0]) ' –

5

Sé que esta es una pregunta muy antigua, pero como la respuesta aceptada es incorrecta, me siento obligado a publicar la mía. Reutilizaré el ejemplo de la respuesta aceptada, ligeramente modificado. (Haciendo la suposición de que las enumeraciones son secuenciales.)

// Incorrect code, do not use! 
enum blah { 
    FIRST = 0, 
    SECOND, // 1 
    THIRD, // 2 
    END  // 3 
}; 
const int blah_count = END - FIRST; 
// And this above would be 3 - 0 = 3, although there actually are 4 items. 

Cualquier desarrollador sabe la razón: count = last - first + 1. Y esto funciona con cualquier combinación de signos (ambos extremos negativos, ambos positivos, o solo el primer extremo negativo). Puedes probar.

// Now, the correct version. 
enum blah { 
    FIRST = 0, 
    SECOND, // 1 
    THIRD, // 2 
    END  // 3 
}; 
const int blah_count = END - FIRST + 1; // 4 

Editar: volviendo a leer el texto, tengo una duda. ¿Eso significa que END no forma parte de los artículos ofrecidos? Esto se ve muy raro para mí, pero bueno, supongo que podría tener sentido ...

+1

La intención es que haya 3 elementos en la enumeración (' FIRST, SECOND & THIRD'), siendo el último un marcador de posición que siempre designa el final de la lista, de modo que si se agregan elementos adicionales, no es necesario cambiar la fórmula para el recuento de elementos. –

+0

Sí, eso es lo que pensé cuando volví a leer unas horas más tarde. Gracias por confirmar. Un comentario al lado de 'END' que dice "No es para ser usado" o algo puede ayudar a entender el código. –

+0

Me gusta usar una convención algo así como "blah_end_marker"; el "end_marker" identifica el propósito, mientras que el prefijo mantiene los marcadores finales distintos. Luego puede definir el conteo, o para enumeraciones "secuenciales" comenzando con 0, use el valor del marcador directamente (por ejemplo, "blah all_blahs [blah_end_marker];" - aunque estoy empezando a pensar que const int blah_count tiene más sentido ... – Bob

-2

Prueba esto:

enter image description here

Es fea y podría haber algunos compiladores que no le gusta, pero usualmente funciona y es útil. Puedes usarlo para cada tipo de enumeración.

+3

Incluya su código como texto formateado en lugar de una imagen. Es útil para poder copiar, pegar y buscar. –

0
#include <stdio.h> 

// M_CONC and M_CONC_ come from https://stackoverflow.com/a/14804003/7067195 
#define M_CONC(A, B) M_CONC_(A, B) 
#define M_CONC_(A, B) A##B 

#define enum_count_suffix _count 
#define count(tag) M_CONC(tag, enum_count_suffix) 
#define countable_enum(tag, ...) \ 
    enum tag {__VA_ARGS__}; \ 
    const size_t count(tag) = sizeof((int []) {__VA_ARGS__})/sizeof(int) 

// The following declares an enum with tag `color` and 3 constants: `red`, 
// `green`, and `blue`. 
countable_enum(color, red, green, blue); 

int main(int argc, char **argv) { 
    // The following prints 3, as expected. 
    printf("number of elements in enum: %d\n", count(color)); 
} 
Cuestiones relacionadas