在C ++中将索引映射到字符串的最简单方法

时间:2008-12-16 09:07:10

标签: string indexing map

要求:

  • 必须能够使用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 个答案:

答案 0 :(得分:1)

最快的执行:构建哈希表。由于您提前了解了索引,因此您甚至可以构建perfect hash table.

最容易编程:使用大量的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。

答案 1 :(得分:1)

这是我坚持的。使用此技术,您需要做的就是包含头文件。您只会实例化您使用的内容。您还可以存储一个完美的哈希表,而不仅仅是Idx&amp; 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);

file:mapper.hh

#include "e2str.hh"

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

file:test.cc

#include "mapper.hh"
int main()
{
   cout << "State: " << MapEnum2Str(State, State_s::GetpMap()) << endl;
   return 0;
}

答案 2 :(得分: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;
}

答案 3 :(得分:0)

Easy way to use variables of enum types as string in C怎么样?

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