2010-07-02 7 views
67
int main() 
{ 

    enum Days{Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday}; 

    Days TheDay; 

    int j = 0; 

    printf("Please enter the day of the week (0 to 6)\n"); 

    scanf("%d",&j); 

    TheDay = Days(j); 

    //how to PRINT THE VALUES stored in TheDay 

    printf("%s",TheDay); // isnt working 

    return 0; 
} 
+0

Su resultado esperado es que se imprime la cadena "Domingo", etc.? – GalacticCowboy

+0

printf ("% d", domingo); // imprime 0 pero quiero obtener la salida inversa. – avi

+0

sí, exactamente el Sr. Galactic !! – avi

Respuesta

71

Enumeraciones en C son números que tienen nombres convenientes dentro de su código. No son cadenas, y los nombres asignados a ellos en el código fuente no están compilados en su programa, por lo que no son accesibles en tiempo de ejecución.

La única forma de obtener lo que desea es escribir usted mismo una función que traduzca el valor de la enumeración en una cadena. P.ej. (Suponiendo aquí que mueva la declaración de enum Days fuera de main):

const char* getDayName(enum Days day) 
{ 
    switch (day) 
    { 
     case Sunday: return "Sunday"; 
     case Monday: return "Monday"; 
     /* etc... */ 
    } 
} 

/* Then, later in main: */ 
printf("%s", getDayName(TheDay)); 

Alternativamente, se puede utilizar una matriz como un mapa, por ejemplo,

const char* dayNames[] = {"Sunday", "Monday", "Tuesday", /* ... etc ... */ }; 

/* ... */ 

printf("%s", dayNames[TheDay]); 

Pero aquí Es probable que desee asignar Sunday = 0 en la enumeración para estar seguro ... No estoy seguro de si el estándar C requiere compiladores para comenzar enumeraciones de 0, aunque la mayoría lo hace (estoy seguro alguien comentará para confirmar o negar esto).

+0

Entendí ... Creo que tendré que hacerlo al revés. Gracias Sr. Tyler. – avi

+2

Aw, me ganaste con la solución de matriz. : P Pero sí, las enumeraciones siempre comienzan en 0 a menos que especifiques un valor diferente. – casablanca

+1

Si confiaba en usar las enumeraciones como índices, preferiría enumerarlas explícitamente. Innecesario de acuerdo con los estándares, pero como compiladores de un grupo no han sido exactamente los mejores en el cumplimiento de los estándares en mi experiencia. – jdmichal

4

enum s en C realmente no funcionan de la manera que usted lo espera. Puede pensar en ellos como una especie de constantes glorificadas (con algunos beneficios adicionales relacionados con ser una colección de tales constantes), y el texto que ha escrito para "Domingo" realmente se resuelve en un número durante la compilación, el el texto finalmente se descarta.

En resumen: para hacer lo que realmente desea, necesitará mantener una serie de cadenas o crear una función para asignar desde el valor de la enumeración al texto que desea imprimir.

0

TheDay regresa a un tipo entero. Por lo tanto:

printf("%s", TheDay); 

intenta analizar theday como una cadena, y, o bien imprimir la basura o un accidente.

printf no es seguro y confía en que le pase el valor correcto. Para imprimir el nombre del valor, necesitaría crear algún método para asignar el valor enum a una cadena, ya sea una tabla de búsqueda, una declaración de cambio gigante, etc.

4

La forma en que generalmente hago esto es almacenando las representaciones de cadena en una matriz separada en el mismo orden, a continuación, la indexación de los matriz con el valor de enumeración:

const char *DayNames[] = { "Sunday", "Monday", "Tuesday", /* etc */ }; 
printf("%s", DayNames[Sunday]); // prints "Sunday" 
+0

¡La mejor respuesta aquí! – Chris

4

enumeraciones en C son básicamente azúcar sintáctica para las listas con nombre de valores enteros secuenciados automáticamente. Es decir, cuando se tiene este código:

int main() 
{ 
    enum Days{Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday}; 

    Days TheDay = Monday; 
} 

su compilador realmente escupe esto:

int main() 
{ 
    int TheDay = 1; // Monday is the second enumeration, hence 1. Sunday would be 0. 
} 

Por lo tanto, la salida de una enumeración C como una cadena no es una operación que tenga sentido para el compilador. Si desea tener cadenas legibles para estos, necesitará definir funciones para convertir de enumeraciones a cadenas.

25

que usar algo como esto:

en un archivo "EnumToString.h ":

#undef DECL_ENUM_ELEMENT 
#undef DECL_ENUM_ELEMENT_VAL 
#undef DECL_ENUM_ELEMENT_STR 
#undef DECL_ENUM_ELEMENT_VAL_STR 
#undef BEGIN_ENUM 
#undef END_ENUM 

#ifndef GENERATE_ENUM_STRINGS 
    #define DECL_ENUM_ELEMENT(element) element, 
    #define DECL_ENUM_ELEMENT_VAL(element, value) element = value, 
    #define DECL_ENUM_ELEMENT_STR(element, descr) DECL_ENUM_ELEMENT(element) 
    #define DECL_ENUM_ELEMENT_VAL_STR(element, value, descr) DECL_ENUM_ELEMENT_VAL(element, value) 
    #define BEGIN_ENUM(ENUM_NAME) typedef enum tag##ENUM_NAME 
    #define END_ENUM(ENUM_NAME) ENUM_NAME; \ 
      const char* GetString##ENUM_NAME(enum tag##ENUM_NAME index); 
#else 
    #define BEGIN_ENUM(ENUM_NAME) const char * GetString##ENUM_NAME(enum tag##ENUM_NAME index) {\ 
     switch(index) { 
    #define DECL_ENUM_ELEMENT(element) case element: return #element; break; 
    #define DECL_ENUM_ELEMENT_VAL(element, value) DECL_ENUM_ELEMENT(element) 
    #define DECL_ENUM_ELEMENT_STR(element, descr) case element: return descr; break; 
    #define DECL_ENUM_ELEMENT_VAL_STR(element, value, descr) DECL_ENUM_ELEMENT_STR(element, descr) 

    #define END_ENUM(ENUM_NAME) default: return "Unknown value"; } } ; 

#endif 

continuación, en cualquier archivo de cabecera a tomar la declaración de enumeración, día enum.h

#include "EnumToString.h" 

BEGIN_ENUM(Days) 
{ 
    DECL_ENUM_ELEMENT(Sunday) //will render "Sunday" 
    DECL_ENUM_ELEMENT(Monday) //will render "Monday" 
    DECL_ENUM_ELEMENT_STR(Tuesday, "Tuesday string") //will render "Tuesday string" 
    DECL_ENUM_ELEMENT(Wednesday) //will render "Wednesday" 
    DECL_ENUM_ELEMENT_VAL_STR(Thursday, 500, "Thursday string") // will render "Thursday string" and the enum will have 500 as value 
    /* ... and so on */ 
} 
END_ENUM(MyEnum) 

a continuación en un archivo llamado EnumToString.c:

#include "enum.h" 

#define GENERATE_ENUM_STRINGS // Start string generation 

#include "enum.h"    

#undef GENERATE_ENUM_STRINGS // Stop string generation 

continuación, en main.c:

int main(int argc, char* argv[]) 
{ 
    Days TheDay = Monday; 
    printf("%d - %s\n", TheDay, GetStringDay(TheDay)); //will print "1 - Monday" 

    TheDay = Thursday; 
    printf("%d - %s\n", TheDay, GetStringDay(TheDay)); //will print "500 - Thursday string" 

    return 0; 
} 

esto generará "a utomatically" las cuerdas para cualquier enumeraciones declararon esta manera y se incluyen en 'EnumToString.c'

+3

Es feo leerlo, pero no tiene duplicación de datos. (A diferencia de todos los demás.) Me da miedo si me gusta esto. –

+1

+1 para la increíble solución creativa sin duplicación de datos y probablemente la mejor capacidad de mantenimiento/flexibilidad, pero ¡yech! Creo que prefiero seguir la ruta const char * []. – manifest

+2

Sí, la capacidad de mantenimiento es increíble! ¡Es muy fácil actualizar cuando cambian los días de la semana! Por cierto, esto ni siquiera es útil para fines de localización ya que la correspondencia entre las cadenas en inglés y los nombres en el programa está ahora codificada de forma rígida por su intento de evitar la duplicación. Al menos con los otros enfoques, es posible traducir las cadenas sin cambiar cada ocurrencia en los archivos fuente. –

3

Aquí está una manera más limpia de hacerlo con macros:

#include <stdio.h> 
#include <stdlib.h> 

#define DOW(X, S)               \ 
    X(Sunday) S X(Monday) S X(Tuesday) S X(Wednesday) S X(Thursday) S X(Friday) S X(Saturday) 

#define COMMA , 

/* declare the enum */ 
#define DOW_ENUM(DOW) DOW 
enum dow { 
    DOW(DOW_ENUM, COMMA) 
}; 

/* create an array of strings with the enum names... */ 
#define DOW_ARR(DOW) [DOW] = #DOW 
const char * const dow_str[] = { 
    DOW(DOW_ARR, COMMA) 
}; 

/* ...or create a switchy function. */ 
static const char * dowstr(int i) 
{ 
#define DOW_CASE(D) case D: return #D 

    switch(i) { 
     DOW(DOW_CASE, ;); 
    default: return NULL; 
    } 
} 


int main(void) 
{ 
    for(int i = 0; i < 7; i++) 
     printf("[%d] = «%s»\n", i, dow_str[i]); 
    printf("\n"); 
    for(int i = 0; i < 7; i++) 
     printf("[%d] = «%s»\n", i, dowstr(i)); 
    return 0; 
} 

No estoy seguro de que esto es totalmente portátil b/w preprocesadores, pero funciona con gcc.

Esto es c99 por cierto, así que use c99 strict si lo conecta a (the online compiler) ideone.

+0

Me encanta cómo son las macros "limpias" :-). – mk12

0

soy nuevo en esto, pero una sentencia switch a trabajar defenitely

#include <stdio.h> 

enum mycolor; 

int main(int argc, const char * argv[]) 

{ 
enum Days{Sunday=1,Monday=2,Tuesday=3,Wednesday=4,Thursday=5,Friday=6,Saturday=7}; 

enum Days TheDay; 


printf("Please enter the day of the week (0 to 6)\n"); 

scanf("%d",&TheDay); 

switch (TheDay) 
{ 

case Sunday: 
     printf("the selected day is sunday"); 
     break; 
    case Monday: 
     printf("the selected day is monday"); 
     break; 
    case Tuesday: 
     printf("the selected day is Tuesday"); 
     break; 
    case Wednesday: 
     printf("the selected day is Wednesday"); 
     break; 
    case Thursday: 
     printf("the selected day is thursday"); 
     break; 
    case Friday: 
     printf("the selected day is friday"); 
     break; 
    case Saturday: 
     printf("the selected day is Saturaday"); 
     break; 
    default: 
     break; 
} 

return 0; 
} 
1

sé que estoy tarde a la fiesta, pero ¿qué tal esto?

const char* dayNames[] = { [Sunday] = "Sunday", [Monday] = "Monday", /*and so on*/ }; 
printf("%s", dayNames[Sunday]); // prints "Sunday" 

De esta manera, usted no tiene que mantener manualmente el y la matriz enumchar* en sincronía. Si es como yo, es probable que más adelante cambie el enum, y el arreglo char* imprimirá cadenas no válidas. Es posible que esta característica no sea universalmente compatible. Pero afaik, la mayoría de los compiladores de C del día de hoy soportan este estilo de inicial designado.

Puede leer más sobre los inicializadores designados here.

0

Me gusta tener enum en el díaNames. Para reducir escribir, podemos hacer lo siguiente:

#define EP(x) [x] = #x /* ENUM PRINT */ 

const char* dayNames[] = { EP(Sunday), EP(Monday)};