从C enum打印文本而不是值

avi*_*avi 81 c enums

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;
}
Run Code Online (Sandbox Code Playgroud)

Tyl*_*nry 89

C中的枚举是代码中具有方便名称的数字.它们不是字符串,源代码中分配给它们的名称不会编译到程序中,因此在运行时无法访问它们.

获得所需内容的唯一方法是自己编写一个函数,将枚举值转换为字符串.例如,(这里假设你移动的声明enum Daysmain):

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));
Run Code Online (Sandbox Code Playgroud)

或者,您可以使用数组作为地图,例如

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

/* ... */

printf("%s", dayNames[TheDay]);
Run Code Online (Sandbox Code Playgroud)

但是在这里你可能想要Sunday = 0在枚举中分配是安全的......我不确定C标准是否要求编译器从0开始枚举,尽管大多数都这样做(我确信有人会评论确认或否认这一点) ).

  • 不要忘记使用C99你可以做`const char*dayNames [] = {[Sunday] ="Sunday",[Monday] ="Monday",[Tuesday] ="Tuesday",/*...等. ..*/};`.您知道,如果一周的日期被重新排序,或者您认为星期一是一周的第一天. (15认同)
  • C标准说,"如果第一个枚举器没有=,则其枚举常数的值为0".但明确表达并不会伤害任何事情. (3认同)
  • 噢,你打败了我的阵列解决方案.:P但是,除非您指定不同的值,否则枚举始终从0开始. (2认同)
  • @ user3467349(预处理器字符串化)只是将#后面的符号转换为字符串.所以,是的,#Monday将变成"星期一",但是"Days TheDay = Monday; printf("%s",#TheDay);`将打印"TheDay". (2认同)

Var*_*gas 28

我使用这样的东西:

在文件"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
Run Code Online (Sandbox Code Playgroud)

然后在任何头文件中进行枚举声明,即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)
Run Code Online (Sandbox Code Playgroud)

然后在一个名为EnumToString.c的文件中:

#include "enum.h"

#define GENERATE_ENUM_STRINGS  // Start string generation

#include "enum.h"             

#undef GENERATE_ENUM_STRINGS   // Stop string generation
Run Code Online (Sandbox Code Playgroud)

然后在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;
}
Run Code Online (Sandbox Code Playgroud)

这将"自动"生成以这种方式声明并包含在"EnumToString.c"中的任何枚举的字符串

  • 阅读起来很难看,但你没有数据重复.(与其他人不同.)我是否喜欢这样. (3认同)
  • 是的,可维护性很棒!当一周中的日子发生变化时,这很容易更新!</嘲讽>顺便说一句,这不是本地化的目的,甚至有用的,因为英文字符串,并在程序中的名称之间的映射,现在由你试图避免重复硬编码.至少使用其他方法,可以转换字符串而不会更改源文件中的每个匹配项. (3认同)
  • +1,这是一个非常有创意的解决方案,没有数据重复,并且可能是最好的可维护性/灵活性,但是是的!我想我还是宁愿走 const char*[] 路线。 (2认同)

for*_*two 6

我知道我参加聚会迟到了,但是这个怎么样?

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

这样,您就不必手动保持enumchar*阵列同步。如果您像我一样,很可能您稍后会更改enum,并且char*数组将打印无效字符串。这可能不是普遍支持的功能。但据我所知,大多数现代 C 编译器都支持这种指定的初始样式。

您可以在此处阅读有关指定初始值设定项的更多信息。


Mar*_*iot 5

enumC 中的 s 并没有真正按照您期望的方式工作。你可以把它们想象成美化的常量(作为这些常量的集合还有一些额外的好处),你为“星期日”写的文本在编译过程中真的被解析为一个数字,文本是最终被丢弃。

简而言之:要执行您真正想要的操作,您需要保留一个字符串数组或创建一个函数以将枚举值映射到您想要打印的文本。


cas*_*nca 5

我通常这样做的方法是将字符串表示以相同的顺序存储在单独的数组中,然后使用枚举值索引数组:

const char *DayNames[] = { "Sunday", "Monday", "Tuesday", /* etc */ };
printf("%s", DayNames[Sunday]); // prints "Sunday"
Run Code Online (Sandbox Code Playgroud)