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;
}
Печатать текст вместо значения из C перечисления
Ответ 1
Перечисления в C - это числа, которые имеют удобные имена внутри вашего кода. Они не являются строками, а имена, назначенные им в исходном коде, не компилируются в вашу программу, поэтому они недоступны во время выполнения.
Единственный способ получить то, что вы хотите, - написать функцию самостоятельно, которая переводит значение перечисления в строку. Например. (предполагая, что вы перемещаете объявление enum Days
вне 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));
В качестве альтернативы вы можете использовать массив в качестве карты, например.
const char* dayNames[] = {"Sunday", "Monday", "Tuesday", /* ... etc ... */ };
/* ... */
printf("%s", dayNames[TheDay]);
Но здесь вы, вероятно, захотите присвоить Sunday = 0
в перечислении, чтобы быть в безопасности... Я не уверен, что для стандарта C требуется, чтобы компиляторы начали перечисление с 0, хотя большинство из них (я уверен, что кто-то будет комментарий, чтобы подтвердить или опровергнуть это).
Ответ 2
Я использую что-то вроде этого:
в файле "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
то в любом файле заголовка вы делаете объявление перечисления, день 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)
то в файле EnumToString.c:
#include "enum.h"
#define GENERATE_ENUM_STRINGS // Start string generation
#include "enum.h"
#undef GENERATE_ENUM_STRINGS // Stop string generation
затем в 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;
}
это будет генерировать "автоматически" строки для любых перечислений, объявленных таким образом и включенных в "EnumToString.c"
Ответ 3
Обычно я делаю это, сохраняя представления строк в отдельном массиве в том же порядке, а затем индексируя массив с значением перечисления:
const char *DayNames[] = { "Sunday", "Monday", "Tuesday", /* etc */ };
printf("%s", DayNames[Sunday]); // prints "Sunday"
Ответ 4
enum
в C не работают так, как вы их ожидаете. Вы можете думать о них как о прославленных константах (с несколькими дополнительными преимуществами, относящимися к набору таких констант), и текст, который вы написали для "воскресенья", действительно получает разрешение на число во время компиляции, текст в конечном счете отброшен.
Короче: для выполнения того, что вы действительно хотите, вам нужно сохранить массив строк или создать функцию для отображения из значения перечисления в текст, который вы хотите распечатать.
Ответ 5
Перечисления на C - это, по сути, синтаксический сахар для названных списков целых чисел с автоматическим упорядочением. То есть, когда у вас есть этот код:
int main()
{
enum Days{Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday};
Days TheDay = Monday;
}
Ваш компилятор действительно выплевывает это:
int main()
{
int TheDay = 1; // Monday is the second enumeration, hence 1. Sunday would be 0.
}
Поэтому вывод C-перечисления в виде строки не является операцией, которая имеет смысл для компилятора. Если вы хотите иметь удобочитаемые строки для них, вам нужно будет определить функции для преобразования из перечислений в строки.
Ответ 6
Здесь более чистый способ сделать это с помощью макросов:
#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;
}
Я не уверен, что это полностью портативные черно-белые препроцессоры, но он работает с gcc.
Это c99 btw, поэтому используйте c99 strict
, если вы подключите его к (онлайн-компилятор) ideone.
Ответ 7
Я знаю, что опаздываю на вечеринку, но как насчет этого?
const char* dayNames[] = { [Sunday] = "Sunday", [Monday] = "Monday", /*and so on*/ };
printf("%s", dayNames[Sunday]); // prints "Sunday"
Таким образом, вам не нужно вручную синхронизировать массив enum
и char*
. Если вы похожи на меня, скорее всего, вы измените значение enum
, а массив char*
напечатает недопустимые строки.
Это может быть не универсальная поддержка. Но afaik, большинство компиляторов mordern day C поддерживают этот назначенный стиль инициализации.
Подробнее о назначенных инициализаторах здесь.
Ответ 8
Вопрос в том, что вы хотите написать имя только один раз.
У меня есть такой идентификатор:
#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";
}
он использует структуру для вставки перечисления, чтобы принтер в строку мог следовать каждому определению значения перечисления.
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
Отличие от enum заключается в том, что builder не может сообщить об ошибке, если числа повторяются.
если вам не нравится запись номера, __LINE__
может заменить его:
#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
Ответ 9
Я новичок в этом, но оператор switch будет работать без проблем
#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;
}
Ответ 10
Мне нравится, что это перечисление в имени дня. Чтобы уменьшить типизацию, мы можем сделать следующее:
#define EP(x) [x] = #x /* ENUM PRINT */
const char* dayNames[] = { EP(Sunday), EP(Monday)};
Ответ 11
TheDay вернется к некоторому целочисленному типу. Итак:
printf("%s", TheDay);
Попытка разбора TheDay в виде строки, а также распечатка мусора или сбой.
printf не является типичным и надеется передать ему правильное значение. Чтобы распечатать имя значения, вам нужно создать некоторый метод для сопоставления значения enum со строкой - либо таблицы поиска, и оператора гигантского переключения и т.д.