Простейший способ отображения индекса на строку в C ++ - PullRequest
0 голосов
/ 16 декабря 2008

Требования:

  • Должен иметь возможность использовать как строки C, так и строки C ++
  • Fast
  • Нет карт
  • Нет шаблонов
  • Нет прямого поиска, т. Е. Индекс может быть за пределами.
  • Индекс не является последовательным
  • Перечисления и строки, содержащиеся в одном заголовочном файле
  • Только создайте экземпляр того, что вы используете.

Вот что я придумал:

- 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 ]

1 голос
/ 23 января 2009

Вот то, на чем я остановился. Используя эту технику, все, что вам нужно сделать, это включить файл заголовка. Вы будете только создавать экземпляр того, что вы используете. Вы также можете хранить идеальную хеш-таблицу вместо 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;
}
1 голос
/ 23 января 2009

Быстрое выполнение: создать хэш-таблицу. Поскольку вы знаете индексы заранее, вы даже можете создать идеальную хэш-таблицу .

Легче всего программировать: используйте массивный оператор 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.

0 голосов
/ 16 декабря 2008

Как насчет Простой способ использовать переменные типов enum в виде строки в C ?

В этом стиле перечисления и строки содержатся не только в одном файле, но и в одном месте. Вы можете легко расширить фабрику, чтобы принимать больше «столбцов» в SOME_ENUM, в вашем случае вы можете захотеть, чтобы строка не генерировалась из имени, а была предоставлена ​​явно.

0 голосов
/ 16 декабря 2008

Я не могу выполнить прямое сопоставление, поскольку одно приложение может выдавать мне значения, которые> находятся вне диапазона моего списка строк. Прямой поиск в небытие будет иметь решающее значение.

Итак, добавьте количество объектов в массив, которые проверяют ваши методы доступа перед возвращением значения:

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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...