• Advertisement

Archived

This topic is now archived and is closed to further replies.

Picking array items by name

This topic is 5845 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

One could think I''ve been programming long enough to know an answer of this but... Anyway I''ve got an array like this: MyType MyArray[10]; And then I pick one of the items: MyArray[3].DoSomething(SomeArgument); Now, for the simplicity of things, I want to be able to give each item in the array a name and then use that name as identifier. Something like this: MyType MyArray[10]; MyArray[0].Name = "Item1" MyArray[1].Name = "AnotherItem" MyArray[2].Name = "AThidItem" ..and so on.. MyArray[AnotherItem].DoSomething(SomeArgument); The point is, that I want to be able to assign a name dynamicly. I know it would have been easy using defines or an enum. Suggestions? -Luctus

Share this post


Link to post
Share on other sites
Advertisement
Guest Anonymous Poster
Your assigning names as strings, so you would want to be able to get the object based on that (string name), no?


I don''t think you can do this w/ a normal array.. this is not perl (in which I''m pretty sure you can).

You''ll have to create an class that mimics an array, and probably create it as a template. And allow the passing of a string as an argument to operator []. Then use the name to search for the object in the array.. Just a suggestion.

Otherwise, you could do enums, but I don''t think you can create new enum values at run time.

Sorry if this didn''t help.

Share this post


Link to post
Share on other sites
std::map is what you''re looking for.


  

#include <map>
#include <string>

using namespace std;

map<string, MyType> MyMap;

// to insert a member

MyType SomeType;
MyMap.insert( make_pair( "Item1", SomeType ) );

// to look it up the easy way

MyType AnotherType = MyMap["Item1"];

// for a faster looking up (i think)

map<string, MyType>::iterator it = MyMap.find("Item1");
if (it == MyMap.end()) {
// "Item1" wasnt found

} else {
// else "Item1" was found

MyType YetAnotherType = (*it).second;

}



This is all from memory so i could be wrong, but it should work.

Share this post


Link to post
Share on other sites
The closest thing to what you want is a map or other associative data structure. What a map does is that it keeps sorted pairs of keys and values (the STL std::map allows only one value per key; std::multimap allows multiple values per key):

#include <map>
std::map< std::string, long > Items;
...
Items[ "You" ] = 0;
Items[ "Me" ] = 1;
...
cout << ( Items[ "Him" ] = 2 ) << endl;


[ GDNet Start Here | GDNet Search Tool | GDNet FAQ | MS RTFM [MSDN] | SGI STL Docs | Google! | Asking Smart Questions | Internet Acronyms ]
Thanks to Kylotan for the idea!

Share this post


Link to post
Share on other sites
I see three ways to solve your problem:

- The first easy way would be to make a fuction that searches through your class array:
MyType* GetObject(char* Object_Name)
...i=0
...while (i < max_number of objects)
......if (strcomp(MyArray.Name, Object_Name) == 0)
.........return MyArray[i]
......i++

It is not reusable. You can create a class manager that holds a pointer to the array and that implements different methods to search or modify your array. A little better design wise, but you are then closer to ...

- The second way is to create a vector of your class and use the find algorithm (STL)
If you are not proficient with vectors and algorithms, look at the following links:
www.sgi.com/tech/stl/
www.devx.com/upload/free/features/vcdj/2000/04apr00/bw0400/bw0400.asp

- The third way is to create your own templated array manager. See the following link to get you started more generally on templates:
http://www.infosys.tuwien.ac.at/Research/Component/tutorial/prwmain.htm

Hope that helps.

Ghostly yours,
Red.

Share this post


Link to post
Share on other sites
Red:
[ source ]
[ /source ]
(without spaces) will put your code in nice little source blocks. Just FYI. Also takes care of problem of italicizing your entire post if you use ''i'' in a subscript. Good posts, btw. Good to have you around.

Share this post


Link to post
Share on other sites
Just to extend what Red Ghost already said, you could make yourself a simple array class and overload operator[] to accept string literals instead of a numeric index. You could do something like this:

  
template<class T>
class array
{
private:
template<class T>
struct node
{
T data;
const char* name;
};

public:
array(unsigned int initial_capacity = 0):
m_capacity(initial_capacity), m_size(0), m_data(0)
{reserve(initial_capacity);}
~array()
{clear();}

unsigned int size() const {return m_size;}
unsigned int capacity() const {return m_capacity;}

void reserve(unsigned int new_capacity)
{
if(new_capacity <= m_capacity)
return;

node<T>* temp = new node<T>[new_capacity];
for(unsigned int = 0; i < m_capacity; ++i)
temp[i] = m_data[i];

delete m_data;
m_data = temp;

m_capacity = new_capacity;
}
void add(const char* name, const T& data)
{
reserve(++m_size);
m_data[m_size+ 1] = data;
}
void clear()
{
delete[] m_data;
m_size = m_capacity = 0;
}

T& operator[](const char* name)
{
for(unsigned int i = 0; i < m_size; ++i)
if(strcmp(m_data[i].name, name) == 0)
return m_data[i].data;

// to keep the compiler happy (we should throw

// an exception before we get here)

return m_data[0].data;
}
const T& operator[](const char* name) const
{
for(unsigned int i = 0; i < m_size; ++i)
if(strcmp(m_data[i].name, name) == 0)
return m_data[i].data;

// to keep the compiler happy (we should throw

// an exception before we get here)

return m_data[0].data;
}

private:
node<T>* m_data;
unsigned int m_capacity;
unsigned int m_size;
};


What can I say? I felt like coding. With this code—assuming that it''s correct—you should be able to do std::vector-like stuff, but using a string literal for access.


  
array<int> stuff(4); // reserve enough space for 4 items, though

// both add and reserve can increase this


stuff.add("Peach", 3);
stuff.add("Banana", 1);
stuff.add("Orange", 5);
stuff.add("Apple", 6);

stuff["Orange"] = 6;
if(stuff["Apple"] == stuff["Orange"])
stuff["Peach"] = 2;

Share this post


Link to post
Share on other sites

  • Advertisement