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;
}
87
Réponses:
Les énumérations en C sont des nombres qui ont des noms pratiques dans votre code. Ce ne sont pas des chaînes et les noms qui leur sont attribués dans le code source ne sont pas compilés dans votre programme et ne sont donc pas accessibles lors de l'exécution.
La seule façon d'obtenir ce que vous voulez est d'écrire vous-même une fonction qui traduit la valeur d'énumération en une chaîne. Par exemple (en supposant ici que vous déplacez la déclaration de l'
enum Days
extérieur demain
):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));
Vous pouvez également utiliser un tableau comme carte, par exemple
const char* dayNames[] = {"Sunday", "Monday", "Tuesday", /* ... etc ... */ }; /* ... */ printf("%s", dayNames[TheDay]);
Mais ici, vous voudrez probablement assigner
Sunday = 0
l'énumération pour être sûr ... Je ne suis pas sûr si le standard C oblige les compilateurs à commencer les énumérations à partir de 0, bien que la plupart le fassent (je suis sûr que quelqu'un commentera pour confirmer ou refuser cela ).la source
const char* dayNames[] = {[Sunday] = "Sunday", [Monday] = "Monday", [Tuesday] = "Tuesday", /* ... etc ... */ };
. Vous savez, au cas où les jours de la semaine seraient réorganisés, ou si vous décidiez que le lundi est le premier jour de la semaine.Days TheDay = Monday; printf("%s", #TheDay);
afficherait "TheDay".J'utilise quelque chose comme ça:
dans un fichier "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
puis dans n'importe quel fichier d'en-tête, vous faites la déclaration enum, day 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)
puis dans un fichier appelé EnumToString.c:
#include "enum.h" #define GENERATE_ENUM_STRINGS // Start string generation #include "enum.h" #undef GENERATE_ENUM_STRINGS // Stop string generation
puis dans 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; }
cela générera "automatiquement" les chaînes pour toutes les énumérations déclarées de cette façon et incluses dans "EnumToString.c"
la source
return _(#element)
et autres.La façon dont je fais généralement cela est de stocker les représentations de chaîne dans un tableau séparé dans le même ordre, puis d'indexer le tableau avec la valeur enum:
const char *DayNames[] = { "Sunday", "Monday", "Tuesday", /* etc */ }; printf("%s", DayNames[Sunday]); // prints "Sunday"
la source
enum
Les s en C ne fonctionnent pas vraiment comme vous l'attendez. Vous pouvez les considérer comme des constantes glorifiées (avec quelques avantages supplémentaires liés au fait d'être une collection de telles constantes), et le texte que vous avez écrit pour "Sunday" est vraiment résolu en un nombre lors de la compilation, le texte est finalement jeté.En bref: pour faire ce que vous voulez vraiment, vous devrez conserver un tableau de chaînes ou créer une fonction pour mapper de la valeur de l'énumération au texte que vous souhaitez imprimer.
la source
Les énumérations en C sont essentiellement du sucre syntaxique pour les listes nommées de valeurs entières séquencées automatiquement. Autrement dit, lorsque vous avez ce code:
int main() { enum Days{Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday}; Days TheDay = Monday; }
Votre compilateur crache en fait ceci:
int main() { int TheDay = 1; // Monday is the second enumeration, hence 1. Sunday would be 0. }
Par conséquent, la sortie d'une énumération C sous forme de chaîne n'est pas une opération qui a du sens pour le compilateur. Si vous souhaitez avoir des chaînes lisibles par l'homme pour celles-ci, vous devrez définir des fonctions à convertir des énumérations en chaînes.
la source
Voici une façon plus propre de le faire avec des 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; }
Je ne suis pas sûr qu'il s'agisse de préprocesseurs n / b totalement portables, mais cela fonctionne avec gcc.
C'est c99 btw, donc utilisez-le
c99 strict
si vous le branchez dans (le compilateur en ligne) ideone .la source
Je sais que je suis en retard à la fête, mais qu'en est-il de ça?
const char* dayNames[] = { [Sunday] = "Sunday", [Monday] = "Monday", /*and so on*/ }; printf("%s", dayNames[Sunday]); // prints "Sunday"
De cette façon, vous n'avez pas à synchroniser manuellement le
enum
et lachar*
baie. Si vous êtes comme moi, il y a de fortes chances que vous changiez plus tard leenum
, et lechar*
tableau affichera des chaînes non valides. Cela peut ne pas être une fonctionnalité universellement prise en charge. Mais afaik, la plupart des compilateurs C modernes prennent en charge ce style initialier désigné.Vous pouvez en savoir plus sur les initialiseurs désignés ici .
la source
La question est que vous voulez écrire le nom une seule fois.
J'ai un ider comme celui-ci:
#define __ENUM(situation,num) \ int situation = num; const char * __##situation##_name = #situation; const struct { __ENUM(get_other_string, -203);//using a __ENUM Mirco make it ease to write, __ENUM(get_negative_to_unsigned, -204); __ENUM(overflow,-205); //The following two line showing the expanding for __ENUM int get_no_num = -201; const char * __get_no_num_name = "get_no_num"; int get_float_to_int = -202; const char * get_float_to_int_name = "float_to_int_name"; }eRevJson; #undef __ENUM struct sIntCharPtr { int value; const char * p_name; }; //This function transform it to string. inline const char * enumRevJsonGetString(int num) { sIntCharPtr * ptr = (sIntCharPtr *)(&eRevJson); for (int i = 0;i < sizeof(eRevJson) / sizeof(sIntCharPtr);i++) { if (ptr[i].value == num) { return ptr[i].p_name; } } return "bad_enum_value"; }
il utilise un struct pour insérer enum, de sorte qu'une imprimante à chaîne puisse suivre chaque valeur d'énumération définie.
int main(int argc, char *argv[]) { int enum_test = eRevJson.get_other_string; printf("error is %s, number is %d\n", enumRevJsonGetString(enum_test), enum_test);
>error is get_other_string, number is -203
La différence avec enum est que le constructeur ne peut pas signaler une erreur si les nombres sont répétés. si vous n'aimez pas écrire le numéro, vous
__LINE__
pouvez le remplacer:#define ____LINE__ __LINE__ #define __ENUM(situation) \ int situation = (____LINE__ - __BASELINE -2); const char * __##situation##_name = #situation; constexpr int __BASELINE = __LINE__; constexpr struct { __ENUM(Sunday); __ENUM(Monday); __ENUM(Tuesday); __ENUM(Wednesday); __ENUM(Thursday); __ENUM(Friday); __ENUM(Saturday); }eDays; #undef __ENUM inline const char * enumDaysGetString(int num) { sIntCharPtr * ptr = (sIntCharPtr *)(&eDays); for (int i = 0;i < sizeof(eDays) / sizeof(sIntCharPtr);i++) { if (ptr[i].value == num) { return ptr[i].p_name; } } return "bad_enum_value"; } int main(int argc, char *argv[]) { int d = eDays.Wednesday; printf("day %s, number is %d\n", enumDaysGetString(d), d); d = 1; printf("day %s, number is %d\n", enumDaysGetString(d), d); }
>day Wednesday, number is 3
>day Monday, number is 1
la source
Je suis nouveau dans ce domaine mais une instruction switch fonctionnera sans aucun doute
#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; }
la source
J'aime que cela ait enum dans le dayNames. Pour réduire la saisie, nous pouvons procéder comme suit:
#define EP(x) [x] = #x /* ENUM PRINT */ const char* dayNames[] = { EP(Sunday), EP(Monday)};
la source
Il existe une autre solution: créez votre propre classe d'énumération dynamique. Cela signifie que vous avez une
struct
fonction et une fonction pour créer une nouvelle énumération, qui stocke les éléments dans astruct
et que chaque élément a une chaîne pour le nom. Vous avez également besoin d'un certain type pour stocker des éléments individuels, des fonctions pour les comparer, etc. Voici un exemple:#include <stdarg.h> #include <stdbool.h> #include <stddef.h> #include <stdio.h> #include <stdlib.h> #include <string.h> struct Enumeration_element_T { size_t index; struct Enumeration_T *parrent; char *name; }; struct Enumeration_T { size_t len; struct Enumeration_element_T elements[]; }; void enumeration_delete(struct Enumeration_T *self) { if(self) { while(self->len--) { free(self->elements[self->len].name); } free(self); } } struct Enumeration_T *enumeration_create(size_t len,...) { //We do not check for size_t overflows, but we should. struct Enumeration_T *self=malloc(sizeof(self)+sizeof(self->elements[0])*len); if(!self) { return NULL; } self->len=0; va_list l; va_start(l,len); for(size_t i=0;i<len;i++) { const char *name=va_arg(l,const char *); self->elements[i].name=malloc(strlen(name)+1); if(!self->elements[i].name) { enumeration_delete(self); return NULL; } strcpy(self->elements[i].name,name); self->len++; } return self; } bool enumeration_isEqual(struct Enumeration_element_T *a,struct Enumeration_element_T *b) { return a->parrent==b->parrent && a->index==b->index; } bool enumeration_isName(struct Enumeration_element_T *a, const char *name) { return !strcmp(a->name,name); } const char *enumeration_getName(struct Enumeration_element_T *a) { return a->name; } struct Enumeration_element_T *enumeration_getFromName(struct Enumeration_T *self, const char *name) { for(size_t i=0;i<self->len;i++) { if(enumeration_isName(&self->elements[i],name)) { return &self->elements[i]; } } return NULL; } struct Enumeration_element_T *enumeration_get(struct Enumeration_T *self, size_t index) { return &self->elements[index]; } size_t enumeration_getCount(struct Enumeration_T *self) { return self->len; } bool enumeration_isInRange(struct Enumeration_T *self, size_t index) { return index<self->len; } int main(void) { struct Enumeration_T *weekdays=enumeration_create(7,"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"); if(!weekdays) { return 1; } printf("Please enter the day of the week (0 to 6)\n"); size_t j = 0; if(scanf("%zu",&j)!=1) { enumeration_delete(weekdays); return 1; } // j=j%enumeration_getCount(weekdays); //alternative way to make sure j is in range if(!enumeration_isInRange(weekdays,j)) { enumeration_delete(weekdays); return 1; } struct Enumeration_element_T *day=enumeration_get(weekdays,j); printf("%s\n",enumeration_getName(day)); enumeration_delete(weekdays); return 0; }
Les fonctions d'énumération devraient être dans leur propre unité de traduction, mais je les ai combinées ici pour le rendre plus simple.
L'avantage est que cette solution est flexible, suit le principe DRY, vous pouvez stocker des informations avec chaque élément, vous pouvez créer de nouvelles énumérations pendant l'exécution et vous pouvez ajouter de nouveaux éléments pendant l'exécution. L'inconvénient est que cela est complexe, nécessite une allocation de mémoire dynamique, ne peut pas être utilisé dans
switch
-case
, nécessite plus de mémoire et est plus lent. La question est de savoir si vous ne devez pas utiliser un langage de niveau supérieur dans les cas où vous en avez besoin.la source
TheDay revient à un type entier. Donc:
printf("%s", TheDay);
Tente d'analyser TheDay sous forme de chaîne et affichera des déchets ou plantera.
printf n'est pas sécurisé et vous fait confiance pour lui transmettre la bonne valeur. Pour imprimer le nom de la valeur, vous devez créer une méthode pour mapper la valeur enum à une chaîne - soit une table de recherche, une instruction de commutateur géant, etc.
la source