• Advertisement
Sign in to follow this  

Enum iteration and enum to text?

This topic is 4736 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have an enum like so: enum WEAPONS { WEAPON_GUN, WEAPON_KNIFE, etc.. } I was wondering if there was a way to iterate through that and convert the enum names to text.

Share this post


Link to post
Share on other sites
Advertisement
Not to my knowledge, though placing something like this right below:

char *weaponnames[]={"weapon_gun","weapon_knife"...};


Allows nice things like this to occur:


cout << weaponnames[player->weapon];


or


for (int x=0;x<WEAPON_MAX;x++){
if (somestring==weaponnames[x]){
return((WEAPONS)(x));
}
}

Share this post


Link to post
Share on other sites
Well, if it helps, each enum value has a number value attached to it. You can designate the start number like this:



enum WEAPONS {

WEAPON_GUN = 1,
WEAPON_KNIFE,
etc...

};




So I'm guessing you could just iterate through them with a for loop, but I'm not completely sure. About giving each one a name, can't help you there, you probably will just have to hard code it. As for the for loop maybe something like this:



for(i = 0; i < MAX_WEAPONS; i++)
weapon = (WEAPONS)i;




That probably won't work though...



Share this post


Link to post
Share on other sites
You can't really "iterate through" an enumeration, because well... there aren't any "things" there to iterate over. (However, since each enumerated value corresponds to a numeric value, you can use a for loop with those values - but those would just be indices; you'd still need an array to index into.) And you can't get the names at runtime, because they don't exist at runtime - those names are just symbol names for the compiler; you can no more access them than you could the names of your variables.

One of the reasons for using enumerations in C++ is that they create a new type. (You can implicitly convert an enumeration value to an integer, but the reverse conversion requires an explicit cast in C++, and heaven help you if you use an invalid integer value there. Oh, in C that conversion does not require an explicit cast.) So, one option is to make a more involved type, using a class:


class Weapon {
int type;
static std::vector<std::string> names;
static int len;
void init();
public:
Weapon(int type = 0) : type(type) {
if (type < 0 || type >= len) {
throw std::range_error("Invalid weapon type");
}
}
Weapon(const std::string& name) {
for (int i = 0; i < len; i++) {
if (names == name) { type = i; return; }
}
throw std::logic_error("No weapon with that name");
}
// Once created, we can see the object's name, but not its ID -
// although we can compare the objects - and can't change its data.
std::string& name() { return names[type]; }
static int numTypes() { return names.length(); }
}
void Weapon::init() {
names = vector();
names.push_back("gun");
names.push_back("knife");
// etc.
len = names.length();
}

// later:
Weapon w(1);
Weapon w2("knife");
if (w == w2) { cout << "Weapon 1 is a knife." << endl; }
cout << "Weapon 0's name: " << Weapon().name();
cout << "There are " << Weapon::numTypes() << " weapons to choose from.";



All off the top of my head, no guarantees of correctness, efficiency, safety or sanity.

Share this post


Link to post
Share on other sites
You can also use std::map... (haven't used it much, but I think its rather good)
 std::map<WEAPONS,std::string> strWeapons;

However, I have not yet learned how to use std::map, so you're going to have to search for that, and tell me if you find any good articles.

Share this post


Link to post
Share on other sites
So basically the answer is no? :)
All of the methods are basically hard coded text, which is what I'm currently using. I was hoping to get away from that, but alas that doesn't seem possible.

Oh well, thanks anyway.

Share this post


Link to post
Share on other sites
I don't think you quite understand why you'd use an enum. It basically takes a plan old number and makes it so that you can understand it easier. So, instead of having something like this:
int weapontype = 3;  // make the weapon type a saw
}
You could have something like this:
enum WEAPONS{ WEAPON_GUN, WEAPON_KNIFE, WEAPON_SAW }

int weapontype = WEAPON_SAW; // More understandable?

Share this post


Link to post
Share on other sites
Quote:

I don't think you quite understand why you'd use an enum.


I do, actually. But that has nothing to do with why I want to conver them to text.

I'm looking to convert enum names into text for my map editor. It'd certainly be easier than showing numbers (the enums actual values) or having to hard code a bunch of text names for each enum.

Share this post


Link to post
Share on other sites
having a corressponding array of strings is a pretty common method. You just have to make sure that they always match up (I usually put a comment above the enum saying that the string list will need to be modified if the enum is modified, on pain of death -_^).

Also, its handy to always have a "count" item as the last enum. eg.


// O M F G BE SURE TO UPDATE WEAPON_NAMES IF YOU MODIFY THIS OTHERWISE CARNAGE WILL ENSUE
enum WEAPONS
{
WEAPON_GUN,
WEAPON_KNIFE,
.
.
.
WEAPON_COUNT
}

const char* WEAPON_NAMES[WEAPON_COUNT] =
{ "gun", "knife", ... };



then you can define an array of weapons, and iterate accross them:


Weapon weapons[WEAPON_COUNT];
for (int i = 0; i < WEAPON_COUNT; i++)
{ blah; }

Share this post


Link to post
Share on other sites
Quote:
Original post by wyrd
So basically the answer is no? :)
All of the methods are basically hard coded text, which is what I'm currently using. I was hoping to get away from that, but alas that doesn't seem possible.

Well, you could make an enum wrapper - essentially a wrapper over an std::map. It's simple, but it's dynamic and you could reuse it for other enums, especially if you've assigned a certain enum group a certain type.

#include <map> // include std::map, obviously
#include <string> // include std::string

// enums of items
enum eItem {
eWeapon,
... other enums
};

template<typename T>
class EnumWrapper
{
public:
void register(T val, std::string match); // set an enum to a string
std::string retreiveSymbol(T key); // return an std::string
T retreive(std::string val); // return the enum for this string
private:
std::map<T, std::string> m_enumMap;
};

// typedef for ease of use
typedef EnumWrapper<Item> ItemEnums;
// make it a global
ItemEnums _itemList;



You could read the names from a file, and register them that way -
if(_enum == eWeapon) { _itemList.register(_enum, "Teh Weapon of Dhoom !!!"); }

Food for thought.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement