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;
}
89
Jawaban:
Pencacahan dalam C adalah angka yang memiliki nama yang sesuai di dalam kode Anda. Mereka bukan string, dan nama yang diberikan padanya di kode sumber tidak dikompilasi ke dalam program Anda, sehingga tidak dapat diakses pada waktu proses.
Satu-satunya cara untuk mendapatkan yang Anda inginkan adalah menulis sendiri fungsi yang menerjemahkan nilai pencacahan menjadi string. Misalnya (dengan asumsi di sini bahwa Anda memindahkan deklarasi di
enum Days
luarmain
):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));
Alternatifnya, Anda bisa menggunakan larik sebagai peta, mis
const char* dayNames[] = {"Sunday", "Monday", "Tuesday", /* ... etc ... */ }; /* ... */ printf("%s", dayNames[TheDay]);
Tetapi di sini Anda mungkin ingin menetapkan
Sunday = 0
dalam pencacahan agar aman ... Saya tidak yakin apakah standar C mengharuskan kompiler untuk memulai pencacahan dari 0, meskipun sebagian besar melakukannya (saya yakin seseorang akan berkomentar untuk mengkonfirmasi atau menyangkal ini ).sumber
const char* dayNames[] = {[Sunday] = "Sunday", [Monday] = "Monday", [Tuesday] = "Tuesday", /* ... etc ... */ };
. Anda tahu, jika hari-hari dalam seminggu diatur ulang, atau Anda memutuskan bahwa Senin adalah hari pertama dalam seminggu.Days TheDay = Monday; printf("%s", #TheDay);
akan mencetak "TheDay".Saya menggunakan sesuatu seperti ini:
dalam file "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
lalu di file header apa pun Anda membuat deklarasi enum, hari 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)
lalu di file bernama EnumToString.c:
#include "enum.h" #define GENERATE_ENUM_STRINGS // Start string generation #include "enum.h" #undef GENERATE_ENUM_STRINGS // Stop string generation
lalu di 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; }
ini akan menghasilkan "secara otomatis" string untuk setiap enum yang dideklarasikan dengan cara ini dan termasuk dalam "EnumToString.c"
sumber
return _(#element)
dan sejenisnya.Cara saya biasanya melakukan ini adalah dengan menyimpan representasi string dalam array terpisah dalam urutan yang sama, kemudian mengindeks array dengan nilai enum:
const char *DayNames[] = { "Sunday", "Monday", "Tuesday", /* etc */ }; printf("%s", DayNames[Sunday]); // prints "Sunday"
sumber
enum
s di C tidak benar-benar berfungsi seperti yang Anda harapkan. Anda dapat menganggapnya seperti konstanta yang dimuliakan (dengan beberapa manfaat tambahan terkait menjadi sebuah koleksi konstanta semacam itu), dan teks yang Anda tulis untuk "Minggu" benar-benar diselesaikan menjadi angka selama kompilasi, teks tersebut akhirnya dibuang.Singkatnya: untuk melakukan apa yang benar-benar Anda inginkan, Anda harus menyimpan array string atau membuat fungsi untuk memetakan dari nilai enum ke teks yang ingin Anda cetak.
sumber
Pencacahan dalam C pada dasarnya adalah gula sintaksis untuk daftar nama dari nilai integer yang diurutkan secara otomatis. Artinya, bila Anda memiliki kode ini:
int main() { enum Days{Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday}; Days TheDay = Monday; }
Kompiler Anda benar-benar mengeluarkan ini:
int main() { int TheDay = 1; // Monday is the second enumeration, hence 1. Sunday would be 0. }
Oleh karena itu, mengeluarkan enumerasi C sebagai string bukanlah operasi yang masuk akal bagi kompilator. Jika Anda ingin memiliki string yang dapat dibaca manusia untuk ini, Anda perlu menentukan fungsi untuk mengubah dari enumerasi menjadi string.
sumber
Berikut cara yang lebih bersih untuk melakukannya dengan makro:
#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; }
Saya tidak yakin apakah ini benar-benar praprosesor b / w portabel, tetapi berfungsi dengan gcc.
Ini adalah c99 btw, jadi gunakan
c99 strict
jika Anda menghubungkannya ke (kompiler online) ideone .sumber
Saya tahu saya terlambat ke pesta, tapi bagaimana dengan ini?
const char* dayNames[] = { [Sunday] = "Sunday", [Monday] = "Monday", /*and so on*/ }; printf("%s", dayNames[Sunday]); // prints "Sunday"
Dengan cara ini, Anda tidak perlu menyinkronkan array
enum
dan secara manualchar*
. Jika Anda seperti saya, kemungkinan besar nanti Anda akan mengubahenum
, danchar*
array akan mencetak string yang tidak valid. Ini mungkin bukan fitur yang didukung secara universal. Tapi afaik, sebagian besar kompiler hari mordern C mendukung gaya penginisialisasi yang ditunjuk ini.Anda dapat membaca lebih lanjut tentang penginisialisasi yang ditentukan di sini .
sumber
Pertanyaannya adalah Anda ingin menulis nama hanya satu kali.
Saya punya ider seperti ini:
#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"; }
ia menggunakan struct untuk memasukkan enum, sehingga printer ke string dapat mengikuti setiap nilai enum yang ditentukan.
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
Perbedaan dengan enum adalah pembangun tidak dapat melaporkan kesalahan jika nomor diulang. Jika Anda tidak suka menulis nomor,
__LINE__
bisa menggantinya:#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
sumber
Saya baru dalam hal ini tetapi pernyataan switch pasti akan berfungsi
#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; }
sumber
Saya suka ini memiliki enum di dayNames. Untuk mengurangi pengetikan, kita bisa melakukan hal berikut:
#define EP(x) [x] = #x /* ENUM PRINT */ const char* dayNames[] = { EP(Sunday), EP(Monday)};
sumber
Ada solusi lain: Buat kelas enumerasi dinamis Anda sendiri. Berarti Anda memiliki
struct
fungsi dan beberapa untuk membuat enumerasi baru, yang menyimpan elemen dalam astruct
dan setiap elemen memiliki string untuk namanya. Anda juga memerlukan beberapa tipe untuk menyimpan elemen individual, fungsi untuk membandingkannya dan sebagainya. Berikut ini contohnya:#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; }
Seharusnya fungsi enumerasi ada di unit terjemahannya masing-masing, tapi di sini saya gabungkan supaya lebih sederhana.
Keuntungannya adalah solusi ini fleksibel, mengikuti prinsip KERING, Anda dapat menyimpan informasi bersama dengan setiap elemen, Anda dapat membuat enumerasi baru selama runtime dan Anda dapat menambahkan elemen baru selama runtime. Kerugiannya adalah ini kompleks, membutuhkan alokasi memori dinamis, tidak dapat digunakan dalam
switch
-case
, membutuhkan lebih banyak memori dan lebih lambat. Pertanyaannya adalah jika Anda tidak boleh menggunakan bahasa tingkat yang lebih tinggi dalam kasus di mana Anda membutuhkannya.sumber
TheDay memetakan kembali ke beberapa tipe integer. Begitu:
printf("%s", TheDay);
Mencoba mengurai TheDay sebagai string, dan akan mencetak sampah atau macet.
printf tidak aman untuk mengetik dan memercayai Anda untuk memberikan nilai yang tepat. Untuk mencetak nama nilainya, Anda perlu membuat beberapa metode untuk memetakan nilai enum ke string - baik tabel pencarian, pernyataan sakelar raksasa, dll.
sumber