En C, ¿hay una buena manera de rastrear el número de elementos en una enumeración? He visto

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

Pero esto sólo funciona si los elementos son secuenciales y comenzar de cero.

InformationsquelleAutor Peter Gibson | 2009-04-03

8 Comentarios

  1. 36

    Yo no creo que exista. Pero, ¿qué haría usted con un número, si no son secuenciales, y usted ya no tiene una lista de ellos en alguna parte? Y si son secuenciales sino a un número diferente, siempre se puede hacer:

    enum blah {
        FIRST = 128,
        SECOND,
        THIRD,
        END
    };
    const int blah_count = END - FIRST;
    • puede tipos enum ser negativo? Si así que cuidado con esto.
    • PRIMERO=-2 sería calcular correctamente, creo que: 1 – (-2) = 3.
    • No necesita mirar hacia fuera; resta funciona bien para los números negativos. Pax tiene derecho.
    • PRIMERO = -200, SEGUNDO = -199, TERCERO = -198, FINAL = -100. -200 – (-100) = malas noticias
    • Uno de los casos que las obras no una prueba de hacer.
    • incluso sequiental que se rompe
    • Me refería secuencial como en sólo establecer el primer valor, y dejar que cada valor restante de incremento por defecto, en la secuencia. enum bla { PRIMERO= <cualquier número a>, SEGUNDO, TERCERO, END };
    • como estoy diciendo pensamiento configuración de la primera a -9 y tener 3 elementos -9 – (-7) = -2. Usted necesita un valor absoluto o algo.
    • No, tendría que llegar PRIMERO = -9 SEGUNDO = -8 TERCERA = -7 END = -6, por lo que tendría -6 – (-9) = -6 + 9 = 3
    • ah, sí… duh…
    • No hay problema, un error fácil de hacer.
    • el valor FINAL puede ser útil si PRIMERO=0 y los valores se utilizan como índices de una matriz estática (por ejemplo, una estática de la matriz de cadenas que describe los valores). A continuación, la matriz puede ser declarada y definida con el tamaño de la ‘FINAL’, por lo tanto no hay necesidad de cambiar su tamaño cada vez que se agrega un valor de la enumeración.
    • enum { E_1 = 0, E_2 = 5, E_3, E_4, E_5 = 10, E_END };, esto va a terminar de error!

  2. 67

    Si no asigna su enumeraciones que usted puede hacer algo como esto:

    enum MyType {
      Type1,
      Type2,
      Type3,
      NumberOfTypes
    }

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

    • Buen truco! claramente la más fácil para los secuencial de las enumeraciones
    • Siempre se puede estar seguro de que en cada implementación en C en cualquier lugar y en todo momento las enumeraciones empezar desde 0? Yo así lo asumimos, pero es siempre verdad?
    • A finales de responder a @JohnyTex, pero el estándar de C menciona en «la Enumeración de los especificadores’: If the first enumerator has no =, the value of its enumeration constant is 0. Each subsequent enumerator with no = defines its enumeration constant as the value of the constant expression obtained by adding 1 to the value of the previous enumeration constant. Así que sí, esto se podría aplicar a cualquier estándares de la adhesión de la implementación.
  3. 23

    Vieja pregunta, lo sé. Esto es para los empleados 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

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

    • Impresionante, de hecho, me vine aquí porque yo estaba buscando una buena manera de determinar el número de los elementos en una X_MACRO, y esta es una buena manera.
    • También se puede simplemente tomar el número de elementos en la val_list matriz mediante la idiomáticas (sizeof val_list / sizeof val_list[0])
    • Probablemente debe ser n = v, aunque,
  4. 5

    Sé que esto es una muy vieja pregunta, pero como el aceptado respuesta es incorrecta, me siento obligado a publicar mi propio. Voy a reutilizar el aceptado la respuesta del ejemplo, 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 programador sabe la razón: count = last - first + 1.
    Y esto funciona con cualquier combinación de los signos (ambos extremos negativo, positivo, o sólo el primer extremo negativo). Usted puede intentar.

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

    Edición: leer el texto de nuevo, tengo una duda. Es que END el propósito de no ser parte de los artículos que se ofrecen? Que parece extraño para mí, pero bueno, supongo que se podría tener sentido…

    • La intención es que hay 3 elementos de la enumeración (FIRST, SECOND & THIRD), con el último siendo un marcador de posición que siempre designa al final de la lista, de modo que si se agregan elementos adicionales no es necesario cambiar la fórmula para el número de elementos.
    • Sí, eso es lo que pensé cuando leí de nuevo un par de horas más tarde. Gracias por la confirmación. Un comentario junto a END que dice «No significa ser usado» o algo podría ayudar a la comprensión del código.
    • Me gusta usar un convenio de algo así como «blah_end_marker»; el «end_marker» identifica el propósito, mientras que el prefijo mantiene los marcadores finales distintos. A continuación, puede definir la cuenta, o para «secuencial» de las enumeraciones de partida con 0, se utiliza el valor del marcador directamente (por ejemplo, «bla all_blahs[blah_end_marker];» – aunque estoy empezando a pensar que la const int blah_count tiene más sentido…
  5. 3

    Bien, ya que las enumeraciones no se puede cambiar en tiempo de ejecución, la mejor cosa que puedes 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 donde la información sería muy útil. De qué están tratando de hacer?

    • Sí ¿por qué quieres hacer eso!
    • Estoy en una situación donde quiero al azar para asignar valores de enumeración para una matriz. Necesito saber cuántos valores diferentes hay para que yo pueda obtener el derecho de la gama.
  6. 3
    int enaumVals[] =
    {
    FIRST,
    SECOND,
    THIRD,
    LAST
    };
    
    #define NUM_ENUMS sizeof(enaumVals) / sizeof ( int );
    • Esto parece requerir la repetición de la totalidad de la enumeración en una matriz, puramente para permitir el uso de sizeof – se ve como el esfuerzo más para mí que sólo #define CONTAR 4
    • En tamaño C que calcula en tiempo de compilación. C no es un lenguaje interpretado, este método es tan eficaz como el uso de una revisión de la definición y simplifica el mantenimiento.
    • Excepto que no lo es. Este va a contaminar los símbolos de su programa con un inútil matriz de NUM_ENUMS int. El programa va a tardar en arrancar, se utiliza más espacio en disco y así sucesivamente. La única manera de evitar esto es para declarar y definir esta en una independiente de la unidad de compilación, pero entonces usted no tiene NUM_ENUMS disponibles, de manera que no funcionan. Más adelante, si usted agrega un nuevo miembro a su enumeración de la lista, puede que se olvide de hacerlo en la matriz y NUM_ENUMS no iguales
  7. 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));
    }
    • esto es bueno de otra manera, pero el OP fue pidiendo específicamente para el recuento de los miembros cuando los valores son explícitamente valorada y no su código se rompería.

Dejar respuesta

Please enter your comment!
Please enter your name here