打印文本而不是C枚举中的值
C语言中的枚举并没有按照您期望的方式工作。你可以认为它们有点像美化的常量(作为此类常量的集合还有一些额外的好处),而你为“Sunday”写的文本在编译过程中确实被分解成了一个数字,文本最终被丢弃打印文本而不是C枚举中的值,c,enums,C,Enums,C语言中的枚举并没有按照您期望的方式工作。你可以认为它们有点像美化的常量(作为此类常量的集合还有一些额外的好处),而你为“Sunday”写的文本在编译过程中确实被分解成了一个数字,文本最终被丢弃 简而言之:要完成真正需要的操作,您需要保留一个字符串数组或创建一个函数,将枚举值映射到要打印的文本。C中的枚举是代码中具有方便名称的数字。它们不是字符串,源代码中指定给它们的名称不会编译到程序中,因此在运行时无法访问它们 获得所需内容的唯一方法是自己编写一个函数,将枚举值转换为字符串。例如(假设您将en
简而言之:要完成真正需要的操作,您需要保留一个字符串数组或创建一个函数,将枚举值映射到要打印的文本。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));
但在这里,您可能希望在枚举中指定
Sunday=0
,以确保安全。。。我不确定C标准是否要求编译器从0开始枚举,尽管大多数编译器是这样做的(我相信会有人对此进行评论以确认或否认)。日期映射回某个整数类型。因此:
const char* dayNames[] = {"Sunday", "Monday", "Tuesday", /* ... etc ... */ };
/* ... */
printf("%s", dayNames[TheDay]);
尝试将日期解析为字符串,并将打印出垃圾或崩溃
printf不是类型安全的,它信任您将正确的值传递给它。要打印出值的名称,您需要创建一些将枚举值映射到字符串的方法—查找表、巨型开关语句等。我通常这样做的方式是将字符串表示形式以相同的顺序存储在单独的数组中,然后用枚举值索引数组:
printf("%s", TheDay);
C中的枚举基本上是自动排序整数值命名列表的语法糖。也就是说,当您拥有此代码时:
const char *DayNames[] = { "Sunday", "Monday", "Tuesday", /* etc */ };
printf("%s", DayNames[Sunday]); // prints "Sunday"
您的编译器实际上会输出以下内容:
int main()
{
enum Days{Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday};
Days TheDay = Monday;
}
因此,将C枚举输出为字符串对于编译器来说不是一个有意义的操作。如果希望这些字符串具有人类可读性,则需要定义函数以将枚举转换为字符串。我使用类似以下内容: 在文件“EnumToString.h”中: 然后在任何头文件中进行enum声明,day enum.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
然后在名为EnumToString.c的文件中:
#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)
然后,在主体c中:
#include "enum.h"
#define GENERATE_ENUM_STRINGS // Start string generation
#include "enum.h"
#undef GENERATE_ENUM_STRINGS // Stop string generation
这将为以这种方式声明并包含在“EnumToString.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;
}
#包括
#包括
#定义道琼斯指数(X,S)\
X(星期日)sx(星期一)sx(星期二)sx(星期三)sx(星期四)sx(星期五)sx(星期六)
#定义逗号,
/*声明枚举*/
#定义道琼斯指数(道琼斯指数)道琼斯指数
枚举道{
道琼斯指数(道琼斯指数,逗号)
};
/*创建具有枚举名称的字符串数组*/
#定义道琼斯指数
常量字符*常量道街[]={
道琼斯指数(道琼斯指数,逗号)
};
/*…或创建切换功能*/
静态常量字符*dowstr(int i)
{
#定义DOW#u案例(D)案例D:返回#D
开关(一){
陶氏(陶氏案例);
默认值:返回NULL;
}
}
内部主(空)
{
对于(int i=0;i<7;i++)
printf(“[%d]=«%s»\n”,i,道富街[i]);
printf(“\n”);
对于(int i=0;i<7;i++)
printf(“[%d]=«%s»\n”,i,dowstr(i));
返回0;
}
我不确定这是否是完全可移植的b/w预处理器,但它可以与gcc一起工作
这是c99 btw,所以如果您将其插入,请使用
c99 strict
。我不熟悉这一点,但switch语句会起到保护作用
#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;
}
#包括
菌色计数;
int main(int argc,const char*argv[]
{
枚举日{星期日=1,星期一=2,星期二=3,星期三=4,星期四=5,星期五=6,星期六=7};
列举每天的天数;
printf(“请输入一周中的哪一天(0到6)\n”);
scanf(“%d”&天);
开关(当日)
{
案件星期日:
printf(“所选日期为星期日”);
打破
案件星期一:
printf(“所选日期为星期一”);
打破
案件星期二:
printf(“所选日期为星期二”);
打破
案件星期三:
printf(“所选日期为星期三”);
打破
案件星期四:
printf(“所选日期为星期四”);
打破
案件星期五:
printf(“所选日期为星期五”);
打破
案件星期六:
printf(“所选日期为星期六”);
打破
违约:
打破
}
返回0;
}
我知道我参加聚会迟到了,但是这个怎么样
#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;
}
这样,您就不必手动使enum
和char*
数组保持同步。如果您像我一样,很可能以后会更改enum
,并且char*
数组将打印无效字符串。
这可能不是普遍支持的功能。不过,大多数现代C编译器都支持这种指定的初始风格
您可以阅读有关指定初始值设定项的更多信息。我喜欢在dayNames中包含enum。 要减少键入,我们可以执行以下操作:
const char* dayNames[] = { [Sunday] = "Sunday", [Monday] = "Monday", /*and so on*/ };
printf("%s", dayNames[Sunday]); // prints "Sunday"
问题是你只想写一次名字。
我有这样的想法:
#定义"枚举(情境,num)\
int情境=num;const char*uu#######name=#情境;
常量结构{
__ENUM(get_other_string,-203);//使用uu ENUM Mirco可以简化编写,
__枚举(得到负的到无符号的-204);
__枚举(溢出,-205);
//下面两行显示了_ENUM的扩展
int get\u no\u num=-201;const char*\u get\u no\u num\u name=“get\u no\u num”;
int get_float_to_int=-202;const char*get_float_to_int_name=“float_to_int_name”;
}eRevJson;
#未定义枚举
结构sIntCharPtr{int value;const char*p_name;};
#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;
}
const char* dayNames[] = { [Sunday] = "Sunday", [Monday] = "Monday", /*and so on*/ };
printf("%s", dayNames[Sunday]); // prints "Sunday"
#define EP(x) [x] = #x /* ENUM PRINT */
const char* dayNames[] = { EP(Sunday), EP(Monday)};
#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;
}