0

要求:

  • 必须能够使用 C 字符串以及 C++ 字符串
  • 快速地
  • 没有地图
  • 没有模板
  • 没有直接查找,即索引可能超出范围。
  • 索引不连续
  • 一个头文件中包含的枚举和字符串
  • 仅实例化您使用的内容。

到目前为止,这是我想出的:

- test.hh -

// Generic mapper
// 
// The idea here is to create a map between an integer and a string.
// By including it inside a class we prevent every module which
// includes this include file from creating their own instance.
//
struct Mapper_s
{
   int Idx;
   const char *pStr;
};

// Status
enum State_t
{
   Running = 1,
   Jumping = 6, 
   Singing = 12
};

struct State_s
{
   static const Mapper_s *GetpMap(void)
   {
       static Mapper_s Map[] = 
       {
            { Running,   "Running" },
            { Jumping,   "Jumping" },
            { Singing,   "Singing" },
            { 0,   0}
        };
        return Map;
    };
};

- test.cc -
// This is a generic function 
const char *MapEnum2Str(int Idx, const Mapper_s *pMap)
{
    int i;
    static const char UnknownStr[] = "Unknown";

    for (i = 0; pMap[i].pStr != 0; i++)
    {
        if (Idx == pMap[i].Idx)
        {
            return pMap[i].pStr;
        }
    }

    return UnknownStr;
}

int main()
{
   cout << "State: " << MapEnum2Str(State, State_s::GetpMap()) << endl;
   return 0;
}

关于如何改进这一点的任何建议?

感觉头文件看起来有点杂乱...

4

4 回答 4

1

最快的执行:建立一个哈希表。由于您提前知道索引,您甚至可以构建一个完美的哈希表。

最容易编程:使用大量 switch 语句,并希望编译器知道如何针对不连续的案例整数进行优化。至少字符串将存在于可执行文件本身的 .text 段中,因此您不需要实例化任何内容:

// Status
enum State_t
{
   Running = 1,
   Jumping = 6, 
   Singing = 12
};

const char *StateToString(State_t state)
{
  switch(state)
  {
    case Running: return "Running";
    case Jumping: return "Jumping";
    case Singing: return "Singing";
    default: return "ERROR"; 
  }
}

您可以将所有内容隐藏在宏中(如 Suma 的链接所建议的那样),因此它不是 WTF。

于 2009-01-23T10:25:15.300 回答
1

这是我决定的。使用这种技术,您需要做的就是包含一个头文件。您只会实例化您使用的内容。您还可以存储一个完美的哈希表,而不仅仅是 Idx 和 pStr。这种方法在 C 中不起作用。

文件:e2str.hh

struct Mapper_s
{
    int Idx;
    const char *pStr;
};

#define ENUM2STR_BEGIN(x) struct x { static const Mapper_s *GetpMap(void) {  static const Enum2StrMap_s Map[] = 
#define ENUM2STR_END      return Map; }; }

const char *MapEnum2Str(int Idx, const Mapper_s *pMap);

文件:mapper.hh

#include "e2str.hh"

ENUM2STR_BEGIN(State_s) 
{
        { Running,   "Running" },
        { Singing,   "Singing" },
        { Jumping,   "Jumping" },
        { 0, 0}
};
ENUM2STR_END;

文件:test.cc

#include "mapper.hh"
int main()
{
   cout << "State: " << MapEnum2Str(State, State_s::GetpMap()) << endl;
   return 0;
}
于 2009-01-23T11:51:53.750 回答
0

我无法进行直接映射,因为一个应用程序可能会向我提供超出我的字符串列表范围的值。直接查找虚无将是至关重要的。

因此,在返回值之前将对象计数添加到访问器检查的数组中:

struct map {
const char *mapping[] = { "Running", "Jumping", "Singing" };
const int count = 3;
}

或者如果你想让它自动化

struct map {
map() { 
  for( count = 0; strlen( mapping[count] ); ++i )
}

const char *mapping[] = { "Running", "Jumping", "Singing", "" };
int count;
}
于 2008-12-16T09:32:23.760 回答
0

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

在这种风格中,枚举和字符串不仅包含在一个文件中,还包含在一个位置。您可以轻松扩展工厂以在 SOME_ENUM 中接受更多“列”,在您的情况下,您可能希望字符串不是从名称生成,而是明确提供。

于 2008-12-16T10:24:35.170 回答