首页 > 解决方案 > 拥有枚举字符串值的好方法

问题描述

我发现自己在 C 中经常使用以下模式:

enum type {String, Number, Unknown};

const char* get_token_type(int type) {
    switch (type) {
        case String: return "String";
        case Number: return "Number";
        default: return "Unknown";
    }
}

有什么不错的选择可以让我将两者合二为一吗?


这是另一种方式,它使用全局并且不确定它有多“干净”,但至少我可以在一个复制粘贴作业中将所有内容设置在顶部。

enum type                {String,  Number,   Unknown};
char type_string[][40] = {"String", "Number","Unknown"};

const char* get_token_type(int type) {
    return type_string[type];
}

标签: c

解决方案


丑陋而缓慢的switch解决方案应该由可读的查找表代替:

const char* const type_string[] = {"String", "Number","Unknown"};

typedef enum {String,  Number, Unknown, type_size} type;

...
type something = ...;
if(something > 0 && something<type_size)
  puts( type_string[something] );

不太推荐但可能的解决方案是“X 宏”。它们很难阅读,并且通常在您无法更改正在维护的程序时使用,以便将所有数据集中到程序中的单个位置。

它看起来像这样:

#include <stdio.h>

#define TYPE_LIST(X) \
  X(String)          \
  X(Number)          \
  X(Unknown)         \

typedef enum 
{
  #define X(x) x,
    TYPE_LIST(X)
  #undef X
  type_size
} type;

const char* const type_string[] = 
{
  #define X(x) [x] = #x,  // array designated initializer using enum constant as index
    TYPE_LIST(X)
  #undef X
};

_Static_assert(sizeof type_string/sizeof *type_string == type_size, 
               "type and type_string mismatch");

int main (void)
{
  printf("%d %d %d\n", String, Number, Unknown);
  printf("%s %s %s\n", type_string[String],
                       type_string[Number], 
                       type_string[Unknown]);

  // or if you really like X macros...
  #define X(x) printf("%d is %s\n", x, #x);
    TYPE_LIST(X)
  #undef X
}

(由于 C90 中枚举语言中的尾随逗号缺陷,这仅适用于标准 C,而不适用于 C90)


推荐阅读