首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在C中使用枚举类型的变量作为字符串的简单方法?

在C中使用枚举类型的变量作为字符串的简单方法?
EN

Stack Overflow用户
提问于 2008-09-29 02:00:25
回答 17查看 113.3K关注 0票数 94

这是我想要做的:

代码语言:javascript
复制
typedef enum { ONE, TWO, THREE } Numbers;

我正在尝试编写一个函数,它将执行类似于以下内容的切换情况:

代码语言:javascript
复制
char num_str[10];
int process_numbers_str(Numbers num) {
  switch(num) {
    case ONE:
    case TWO:
    case THREE:
    {
      strcpy(num_str, num); //some way to get the symbolic constant name in here?
    } break;
    default:
      return 0; //no match
  return 1;
}

有没有办法像上面那样使用枚举变量设置它,而不是在每种情况下都定义?

EN

回答 17

Stack Overflow用户

回答已采纳

发布于 2008-09-29 02:06:35

没有内置的解决方案。最简单的方法是使用char*数组,其中枚举的int值索引到包含该枚举的描述性名称的字符串。如果您有一个稀疏enum (不是从0开始或者编号中有间隙),其中一些int映射足够高,使得基于数组的映射不切实际,那么您可以改用哈希表。

票数 16
EN

Stack Overflow用户

发布于 2008-10-14 19:33:50

这里可以使用来自Making something both a C identifier and a string?的技术。

与通常的预处理器一样,编写和理解预处理器部分可能很难,包括将宏传递给其他宏,还涉及使用#和##操作符,但使用它确实很容易。我发现这种风格对于长枚举非常有用,在长枚举中,维护相同的列表两次可能真的很麻烦。

工厂代码-只键入一次,通常隐藏在标题中:

枚举Factory.h:

代码语言:javascript
复制
// expansion macro for enum value definition
#define ENUM_VALUE(name,assign) name assign,

// expansion macro for enum to string conversion
#define ENUM_CASE(name,assign) case name: return #name;

// expansion macro for string to enum conversion
#define ENUM_STRCMP(name,assign) if (!strcmp(str,#name)) return name;

/// declare the access function and define enum values
#define DECLARE_ENUM(EnumType,ENUM_DEF) \
  enum EnumType { \
    ENUM_DEF(ENUM_VALUE) \
  }; \
  const char *GetString(EnumType dummy); \
  EnumType Get##EnumType##Value(const char *string); \

/// define the access function names
#define DEFINE_ENUM(EnumType,ENUM_DEF) \
  const char *GetString(EnumType value) \
  { \
    switch(value) \
    { \
      ENUM_DEF(ENUM_CASE) \
      default: return ""; /* handle input error */ \
    } \
  } \
  EnumType Get##EnumType##Value(const char *str) \
  { \
    ENUM_DEF(ENUM_STRCMP) \
    return (EnumType)0; /* handle input error */ \
  } \

工厂使用

某些Enum.h:

代码语言:javascript
复制
#include "enumFactory.h"
#define SOME_ENUM(XX) \
    XX(FirstValue,) \
    XX(SecondValue,) \
    XX(SomeOtherValue,=50) \
    XX(OneMoreValue,=100) \

DECLARE_ENUM(SomeEnum,SOME_ENUM)

someEnum.cpp:

代码语言:javascript
复制
#include "someEnum.h"
DEFINE_ENUM(SomeEnum,SOME_ENUM)

该技术可以很容易地扩展,以便XX宏接受更多的参数,并且您还可以准备更多的宏来替换XX以满足不同的需求,类似于我在本示例中提供的三个宏。

与使用#include / #define / #undef的X-Macros的比较

虽然这与其他人提到的X-Macros类似,但我认为这个解决方案更优雅,因为它不需要#undefing任何东西,这允许你隐藏更多复杂的东西在工厂头文件-当你需要定义一个新的枚举时,头文件是你根本不会接触的东西,因此新的枚举定义要短得多,更干净。

票数 72
EN

Stack Overflow用户

发布于 2008-09-29 05:00:34

代码语言:javascript
复制
// Define your enumeration like this (in say numbers.h);
ENUM_BEGIN( Numbers )
    ENUM(ONE),
    ENUM(TWO),
    ENUM(FOUR)
ENUM_END( Numbers )

// The macros are defined in a more fundamental .h file (say defs.h);
#define ENUM_BEGIN(typ) enum typ {
#define ENUM(nam) nam
#define ENUM_END(typ) };

// Now in one and only one .c file, redefine the ENUM macros and reinclude
//  the numbers.h file to build a string table
#undef ENUM_BEGIN
#undef ENUM
#undef ENUM_END
#define ENUM_BEGIN(typ) const char * typ ## _name_table [] = {
#define ENUM(nam) #nam
#define ENUM_END(typ) };
#undef NUMBERS_H_INCLUDED   // whatever you need to do to enable reinclusion
#include "numbers.h"

// Now you can do exactly what you want to do, with no retyping, and for any
//  number of enumerated types defined with the ENUM macro family
//  Your code follows;
char num_str[10];
int process_numbers_str(Numbers num) {
  switch(num) {
    case ONE:
    case TWO:
    case THREE:
    {
      strcpy(num_str, Numbers_name_table[num]); // eg TWO -> "TWO"
    } break;
    default:
      return 0; //no match
  return 1;
}

// Sweet no ? After being frustrated by this for years, I finally came up
//  with this solution for my most recent project and plan to reuse the idea
//  forever
票数 61
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/147267

复制
相关文章

相似问题

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