首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何将枚举类型变量转换为字符串?

如何将枚举类型变量转换为字符串?
EN

Stack Overflow用户
提问于 2011-02-24 00:07:38
回答 28查看 259.1K关注 0票数 152

如何让printf显示枚举类型变量的值?例如:

代码语言:javascript
复制
typedef enum {Linux, Apple, Windows} OS_type; 
OS_type myOS = Linux;

我需要的是这样的东西

代码语言:javascript
复制
printenum(OS_type, "My OS is %s", myOS);

它必须显示字符串"Linux",而不是整数。

我想,首先我必须创建一个值索引的字符串数组。但我不知道这是不是最好的方式。这是完全可能的吗?

EN

回答 28

Stack Overflow用户

回答已采纳

发布于 2011-02-24 00:20:40

真的没有什么好的方法可以做到这一点。只需设置一个由枚举索引的字符串数组。

如果您进行了大量输出,则可以定义一个接受枚举参数并为您执行查找的operator<<。

票数 79
EN

Stack Overflow用户

发布于 2011-02-24 01:21:32

当然,最简单的解决方案是为每个执行字符串转换的枚举编写一个函数:

代码语言:javascript
复制
enum OS_type { Linux, Apple, Windows };

inline const char* ToString(OS_type v)
{
    switch (v)
    {
        case Linux:   return "Linux";
        case Apple:   return "Apple";
        case Windows: return "Windows";
        default:      return "[Unknown OS_type]";
    }
}

然而,这是一场维护灾难。在可以与C和C++代码一起使用的Boost.Preprocessor库的帮助下,您可以轻松地利用预处理器并让它为您生成此函数。生成宏如下:

代码语言:javascript
复制
#include <boost/preprocessor.hpp>

#define X_DEFINE_ENUM_WITH_STRING_CONVERSIONS_TOSTRING_CASE(r, data, elem)    \
    case elem : return BOOST_PP_STRINGIZE(elem);

#define DEFINE_ENUM_WITH_STRING_CONVERSIONS(name, enumerators)                \
    enum name {                                                               \
        BOOST_PP_SEQ_ENUM(enumerators)                                        \
    };                                                                        \
                                                                              \
    inline const char* ToString(name v)                                       \
    {                                                                         \
        switch (v)                                                            \
        {                                                                     \
            BOOST_PP_SEQ_FOR_EACH(                                            \
                X_DEFINE_ENUM_WITH_STRING_CONVERSIONS_TOSTRING_CASE,          \
                name,                                                         \
                enumerators                                                   \
            )                                                                 \
            default: return "[Unknown " BOOST_PP_STRINGIZE(name) "]";         \
        }                                                                     \
    }

第一个宏(以X_开头)由第二个宏在内部使用。第二个宏首先生成枚举,然后生成一个ToString函数,该函数接受该类型的对象并以字符串形式返回枚举器名称(由于显而易见的原因,此实现要求枚举器映射到唯一值)。

在C++中,您可以将ToString函数实现为operator<<重载,但我认为需要一个显式的"ToString“来将值转换为字符串形式会更简洁一些。

作为使用示例,您的OS_type枚举的定义如下:

代码语言:javascript
复制
DEFINE_ENUM_WITH_STRING_CONVERSIONS(OS_type, (Linux)(Apple)(Windows))

虽然宏最初看起来像是做了很多工作,而且OS_type的定义看起来相当陌生,但请记住,您必须编写一次宏,然后才能在每次枚举中使用它。你可以毫不费力地向它添加额外的功能(例如,字符串形式到枚举的转换),而且它完全解决了维护问题,因为当你调用宏时,你只需要提供一次名称。

然后,可以像正常定义枚举一样使用枚举:

代码语言:javascript
复制
#include <iostream>

int main()
{
    OS_type t = Windows;
    std::cout << ToString(t) << " " << ToString(Apple) << std::endl;
}

这篇文章中的代码片段,从#include <boost/preprocessor.hpp>行开始,可以像文章一样编译,以演示解决方案。

这个特殊的解决方案是针对C++的,因为它使用了C++特定的语法(例如,没有typedef enum)和函数重载,但它也可以直接用于C语言。

票数 138
EN

Stack Overflow用户

发布于 2011-02-24 00:19:19

这是预处理器模块

代码语言:javascript
复制
#ifndef GENERATE_ENUM_STRINGS
    #define DECL_ENUM_ELEMENT( element ) element
    #define BEGIN_ENUM( ENUM_NAME ) typedef enum tag##ENUM_NAME
    #define END_ENUM( ENUM_NAME ) ENUM_NAME; \
            char* getString##ENUM_NAME(enum tag##ENUM_NAME index);
#else
    #define DECL_ENUM_ELEMENT( element ) #element
    #define BEGIN_ENUM( ENUM_NAME ) char* gs_##ENUM_NAME [] =
    #define END_ENUM( ENUM_NAME ) ; char* getString##ENUM_NAME(enum \
            tag##ENUM_NAME index){ return gs_##ENUM_NAME [index]; }
#endif

枚举定义

代码语言:javascript
复制
BEGIN_ENUM(OsType)
{
    DECL_ENUM_ELEMENT(WINBLOWS),
    DECL_ENUM_ELEMENT(HACKINTOSH),
} END_ENUM(OsType)

调用使用

getStringOsType(WINBLOWS);

摘自here。多酷啊?:)

票数 36
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5093460

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档