Message
| Now that you are using STL and C++, it might be a good idea to look at moving away from static buffers for strings.
Depending on what MSL is defined as (4096 in my version) then you are either:
- Using too much memory, and wasting (say) 4,000 bytes of RAM which is never used; or
- Not allowing enough, in which case one day it will overflow and crash
The version below takes the same arguments as yours, and still returns a const char * string, but uses a string internally, which can never overflow. I have declared it as static so it doesn't go out of scope too soon ...
#ifdef WIN32
#pragma warning( disable : 4786)
#endif
#include <bitset>
#include <string>
#include <iostream>
#include <stdio.h>
using namespace std;
char * const npc_race [] =
{
"human", "elf", "dwarf", "halfling", "pixie", "vampire", "half-ogre",
"half-orc", "half-troll", "half-elf", "gith", "drow", "sea-elf",
"lizardman", "gnome", "r5", "r6", "r7", "r8", "troll",
"ant", "ape", "baboon", "bat", "bear", "bee",
"beetle", "boar", "bugbear", "cat", "dog", "dragon", "ferret", "fly",
"gargoyle", "gelatin", "ghoul", "gnoll", "gnome", "goblin", "golem",
"gorgon", "harpy", "hobgoblin", "kobold", "lizardman", "locust",
"lycanthrope", "minotaur", "mold", "mule", "neanderthal", "ooze", "orc",
"rat", "rustmonster", "shadow", "shapeshifter", "shrew", "shrieker",
"skeleton", "slime", "snake", "spider", "stirge", "thoul", "troglodyte",
"undead", "wight", "wolf", "worm", "zombie", "bovine", "canine", "feline",
"porcine", "mammal", "rodent", "avis", "reptile", "amphibian", "fish",
"crustacean", "insect", "spirit", "magical", "horse", "animal", "humanoid",
"monster", "god"
};
template <class T>
const char * bitset_to_string (T bits, char *const flagarray[] )
{
static string s;
s.clear ();
for (size_t i = 0; i < bits.size (); i++)
if (bits [i])
{
if (!s.empty ())
s += " "; // separate multiple ones by a space
s += flagarray [i];
}
return s.c_str ();
} // end of bitset_to_string
int main (void)
{
bitset<100> race_flags;
race_flags.set (5);
race_flags.set (6);
race_flags.set (70);
printf ("results = '%s'\n", bitset_to_string (race_flags, npc_race) );
}
The only problem with the code above is that it doesn't handle spaces inside your constants, which I think your code does. The version below which introduces a couple more routines that I wrote to trim spaces, will handle spaces at either end of the constants (see the spaces I added to "worm" below) ...
#ifdef WIN32
#pragma warning( disable : 4786)
#endif
#include <bitset>
#include <string>
#include <iostream>
#include <stdio.h>
using namespace std;
char * const npc_race [] =
{
"human", "elf", "dwarf", "halfling", "pixie", "vampire", "half-ogre",
"half-orc", "half-troll", "half-elf", "gith", "drow", "sea-elf",
"lizardman", "gnome", "r5", "r6", "r7", "r8", "troll",
"ant", "ape", "baboon", "bat", "bear", "bee",
"beetle", "boar", "bugbear", "cat", "dog", "dragon", "ferret", "fly",
"gargoyle", "gelatin", "ghoul", "gnoll", "gnome", "goblin", "golem",
"gorgon", "harpy", "hobgoblin", "kobold", "lizardman", "locust",
"lycanthrope", "minotaur", "mold", "mule", "neanderthal", "ooze", "orc",
"rat", "rustmonster", "shadow", "shapeshifter", "shrew", "shrieker",
"skeleton", "slime", "snake", "spider", "stirge", "thoul", "troglodyte",
"undead", "wight", "wolf", " worm ", "zombie", "bovine", "canine", "feline",
"porcine", "mammal", "rodent", "avis", "reptile", "amphibian", "fish",
"crustacean", "insect", "spirit", "magical", "horse", "animal", "humanoid",
"monster", "god"
};
#define SPACES " \t\r\n" // default "spaces" for trimming strings
// trim spaces from right (you can define what spaces are)
string trim_right (const string & s, const string & t = SPACES);
// trim spaces from left
string trim_left (const string & s, const string & t = SPACES);
// trim spaces from both sides
string trim (const string & s, const string & t = SPACES);
inline string trim_right (const string & s, const string & t)
{
string d (s);
string::size_type i (d.find_last_not_of (t));
if (i == string::npos)
return "";
else
return d.erase (d.find_last_not_of (t) + 1) ;
} // end of trim_right
inline string trim_left (const string & s, const string & t)
{
string d (s);
return d.erase (0, s.find_first_not_of (t)) ;
} // end of trim_left
inline string trim (const string & s, const string & t)
{
string d (s);
return trim_left (trim_right (d, t), t) ;
} // end of trim
template <class T>
const char * bitset_to_string (T bits, char *const flagarray[] )
{
static string s;
s.clear ();
for (size_t i = 0; i < bits.size (); i++)
if (bits [i])
s += trim (flagarray [i]) + " ";
s = trim_right (s); // get rid of final space
return s.c_str ();
} // end of bitset_to_string
int main (void)
{
bitset<100> race_flags;
race_flags.set (5);
race_flags.set (6);
race_flags.set (70);
printf ("results = '%s'\n", bitset_to_string (race_flags, npc_race) );
}
Output
results = 'vampire half-ogre worm'
In the second example above, the implementations of trim, trim_left and trim_right *can* be moved into a cpp file (not a header file) because they are straight functions, not templated functions.
|
- Nick Gammon
www.gammon.com.au, www.mushclient.com | Top |
|