0

I am trying to build a map with a custom comparator, however, something that I can not figure it out goes wrong, being unable to add item to the map (specifically, can only add the first item)

struct byKey { bool operator () ( const Key &key1, const Key &key2) const { return key1.keytoInt() < key2.keytoInt(); } }; 

where Key class has a private char[5], like

char[0]=1, char[1]=2, char[3]=13, char[4]=20, char[5]=28 

there is a matching going that ensures all the character in char digit[5] (is less than 32) and can be converted to a character.like char=0, it will search a table, find a character like A

I use a method in Key to covert it to int, then compare with int

int Key :: keytoInt() const{ int sum; sum=atoi(digit); return sum; } 

I build a table of map with key and value both as Key type, however, when trying to test it, I can not add items to the table, I am not sure where goes wrong.

No compile error, however, logically, even though I have inserted into the map three times, the map.size() shows there is only one

map<Key,Key,byKey> firstmap; map<Key,Key>::iterator it; firstmap.insert(pair<Key,Key>(base,stepguess)); firstmap.insert(pair<Key,Key>(stepguess,base)); firstmap[stepguess]=base; cout << "wait"; cout << "mymap.size() is " << firstmap.size() << '\n'; 
4
  • @avarookie Plese describe in words what function keytoInt has to do. Commented Apr 13, 2014 at 1:09
  • 'I am not sure where goes wrong.' What goes wrong, actually?? Compilation errors, unexpected behavior? Edit your question to give this information please. Commented Apr 13, 2014 at 1:20
  • Why don't you overload the operator< for your Key class. Then you don't have to specify a custom comparative for STL map. Commented Apr 13, 2014 at 1:21
  • It looks like the key characteristics have to be thought through again. The behavior described so far implies using a std::string as the map key. No more calls to atoi would be required, and the struct byKey goes away. Also remember that the map can be sorted in ascending or descending order by using the less <T> or greater<T> in the third parameter of the map instance declaration. Commented Apr 13, 2014 at 2:54

2 Answers 2

2

Any time you're converting your key to an integer to compare that way, you're probably better off just comparing the fields directly. In this particular case, consider using memcmp, e.g.:

bool operator()(const Key& lhs, const Key& rhs) { return memcmp(lhs.digit, rhs.digit, sizeof(Key::digit)) < 0; } 

atoi in this case will always return 0 unless you have values which are valid ASCII digits (which these are not).

Sign up to request clarification or add additional context in comments.

Comments

1

So, here's what I know:

class Key { public: int keyToInt() const { return atoi(digit); } private: char digit[5]; }; 

You've also suggested, that there is an example Key that has:

Key k; k.digit = {1, 2, 13, 20, 28}; 

In this case, you have 2 errors:

  1. digit is not null terminated. So calling atoi() on it is undefined behavior.
  2. The ascii characters in digit are not numbers, so you're going to get unhelpful results.

We can also build up a complete test case that shows that std::map is sane.

#include <map> #include <cassert> #include <cstring> class Key { public: Key() { strncpy(m_digit, "0", 5); assert(m_digit[4] == '\0'); } Key(const char *digit) { strncpy(m_digit, digit, 5); assert(m_digit[4] == '\0'); } int keyToInt() const { return atoi(m_digit); } private: char m_digit[5]; }; struct byKey { bool operator () ( Key const & key1, Key const & key2) const { return key1.keyToInt() < key2.keyToInt(); } }; int main() { std::map<Key, Key, byKey> myMap; Key a("123"); Key b("234"); myMap[a] = b; myMap[b] = a; assert(myMap.size() == 2); } 

2 Comments

for error 2, there is a matching going that ensures all the character in char digit[5] (is less than 32) and can be converted to a character.like char=0, it will search a table, find a character like A so, it's not a bother
Without a compliable test case that you can show us, it will be difficult to diagnose your issue then. I've added an example of what that test case might look like.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.