Easiest way to map an index to a string in C ++

Requirements:

  • Should be able to use C strings as well as C ++ strings
  • Fast
  • No cards
  • No templates
  • There is no direct search, i.e. the index can be outside.
  • The index is not consistent
  • Enumerations and Lines Contained in One Header File
  • Indicate only what you are using.

This is what I have come up with so far:

- 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;
}

      

Any suggestions for improving this?

I feel like the header file looks a little cluttered ...

0


source to share


4 answers


Here's what I solved. Using this technique, all you have to do is include the header file. You will only create an instance of what you are using. You can also store a perfect hash table instead of Idx and pStr. This approach does not work in C.

file: 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;
}

      

+1


source


Fastest accomplishment: Build a hash table. Since you know the indexes ahead of time, you can even build a perfect hash table.

Easiest to program: use a massive switch statement and hope the compiler knows how to optimize for incompatible integers. At least the lines will live in the .text segment of the executable itself, so you don't need to create any instances:



// 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"; 
  }
}

      

You can hide it all inside macros (as Suma's link suggests), so it's not much WTF.

+1


source


I cannot do a direct match as one application might be loading me values โ€‹โ€‹that are> out of range for my list of strings. A direct search into nothingness would be critical.

So, add the number of objects to the array that your accessors check before returning a value:

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

      

or if you want to automate

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

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

      

0


source


How about an easy way to use variable enum types as a string in C ?

In this style, enums and lines are not only contained in the same file, but also contained in the same place. You can easily extend the factory to accept more "columns" in SOME_ENUM, in your case you may want the string not to be generated from the name, but provided explicitly.

0


source







All Articles