tags:

views:

275

answers:

2

I have a requirement to create two different maps in C++. The Key is of type CHAR* and the Value is a pointer to a struct. I am filling 2 maps with these pairs, in separate iterations. After creating both maps I need find all such instances in which the value of the string referenced by the CHAR* are same.

For this I am using the following code :

typedef struct _STRUCTTYPE
{
.. 
} STRUCTTYPE, *PSTRUCTTYPE;

typedef pair <CHAR *,PSTRUCTTYPE> kvpair;

..

CHAR *xyz;

PSTRUCTTYPE abc;

// after filling the information;

Map.insert (kvpair(xyz,abc));


// the above is repeated x times for the first map, and y times for the second map.
// after both are filled out;

std::map<CHAR *, PSTRUCTTYPE>::iterator Iter,findIter;

for (Iter=iteratedMap->begin();Iter!=iteratedMap->end();mapIterator++)
{
  char *key = Iter->first;

  printf("%s\n",key);

  findIter=otherMap->find(key);

  //printf("%u",findIter->second);

  if (findIter!=otherMap->end())
  {
    printf("Match!\n");
  }
}

The above code does not show any match, although the list of keys in both maps show obvious matches. My understanding is that the equals operator for CHAR * just equates the memory address of the pointers.

My question is, what should i do to alter the equals operator for this type of key or could I use a different datatype for the string?

+3  A: 

My understanding is that the equals operator for CHAR* just equates the memory address of the pointers.

Your understanding is correct.

The easiest thing to do would be to use std::string as the key. That way you get comparisons for the actual string value working without much effort:

std::map<std::string, PSTRUCTTYPE> m;
PSTRUCTTYPE s = bar();
m.insert(std::make_pair("foo", s));

if(m.find("foo") != m.end()) {
    // works now
}

Note that you might leak memory for your structs if you don't always delete them manually. If you can't store by value, consider using smart pointers instead.

Depending on your usecase, you don't have to neccessarily store pointers to the structs:

std::map<std::string, STRUCTTYPE> m;
m.insert(std::make_pair("foo", STRUCTTYPE(whatever)));

A final note: typedefing structs the way you are doing it is a C-ism, in C++ the following is sufficient:

typedef struct STRUCTTYPE {
    // ...
} *PSTRUCTTYPE;
Georg Fritzsche
Actually my code uses sprintf() a lot, so i'l have to change those occurrences . I'l get back to you once I have made those changes. Thanks anyway :)
Soumava
i did the sprintf and got the string in a char* key and then did std::string key1 = key;seems to work now. :) thanks.
Soumava
A note on PSTRUCTTYPE - typedefing which hides the fact that something is a pointer is considered by many to be bad style.
anon
A: 

If you use std::string instead of char * there are more convenient comparison functions you can use. Also, instead of writing your own key matching code, you can use the STL set_intersection algorithm (see here for more details) to find the shared elements in two sorted containers (std::map is of course sorted). Here is an example

typedef map<std::string, STRUCTTYPE *> ExampleMap;  
ExampleMap inputMap1, inputMap2, matchedMap;

// Insert elements to input maps
inputMap1.insert(...);

// Put common elements of inputMap1 and inputMap2 into matchedMap
std::set_intersection(inputMap1.begin(), inputMap1.end(), inputMap2.begin(), inputMap2.end(), matchedMap.begin());

for(ExampleMap::iterator iter = matchedMap.begin(); iter != matchedMap.end(); ++iter)
{
    // Do things with matched elements
    std::cout << iter->first << endl;
}
Rodion Ingles
thats a very useful functionality..cuts down on a lot of code. thanks.
Soumava