Reputation: 573
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';
Upvotes: 0
Views: 82
Reputation: 81926
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:
digit
is not null terminated. So calling atoi()
on it is undefined behavior.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);
}
Upvotes: 1
Reputation: 5314
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).
Upvotes: 2