Dec 8, 2011 at 3:50am UTC
I am trying to create a map with a custom key - I added some test code, after adding few records, I am able to dump the container contents. For some reason the lookup for the third record fails - I suspect the "operator <" function. Could someone help me findout where I am going wrong?
Here is the code
==
#include <iostream>
#include <map>
using namespace std;
typedef struct _stat
{
uint16_t NodeId;
uint16_t Index;
char *Data;
unsigned long Tx;
unsigned long Rx;
} stats_t;
// map to hold stats data
class MyKey
{
private:
uint16_t m_nodeId;
uint16_t m_index;
unsigned char *m_data;
public:
//Constructor
MyKey( uint16_t nodeId,
uint16_t index,
const char* data)
{
m_nodeId = nodeId;
m_index = index;
m_data = (unsigned char *)data;
}
// Operator routine for map ops
bool operator<(const MyKey& param) const
{
if ( (m_nodeId == param.m_nodeId) &&
(m_index == param.m_index) &&
strcmp((const char *)m_data, (const char *)param.m_data) == 0)
{
return false;
}
return true;
}
};
typedef map<MyKey, stats_t *, less<MyKey> > StatsContainer_t;
typedef StatsContainer_t::iterator StatsIT;
StatsContainer_t m_Stats;
// Routines
void dump(stats_t& P) {
cout << endl;
cout << "Node Id:" << P.NodeId << " Index:" << P.Index << " Data:" << P.Data;
// cout << "Tx : " << P.Tx << endl;
// cout << "Rx : " << P.Rx << endl;
}
void show()
{
StatsIT it = m_Stats.begin();
stats_t *pRec = 0;
cout << "==== Start dump container data =====" << endl;
while(it != m_Stats.end()) {
pRec = it->second;
dump(*pRec);
it++;
}
cout << endl << "==== End dump container data ======" << endl;
}
main() {
stats_t S[6];
stats_t tmpS[6];
char Buf[32] = {'0'};
int ctr = 0;
StatsIT it;
// Add entries into the container
for (; ctr < 6; ctr++)
{
memset(&S[ctr], 0, sizeof(stats_t));
S[ctr].Data = (char *)malloc(10);
memset(S[ctr].Data, 0, 10);
S[ctr].NodeId = ctr;
S[ctr].Index = 1;
sprintf(Buf, "Test-%d", ctr);
strncpy((char *)S[ctr].Data, Buf, strlen(Buf));
srand(time(NULL));
S[ctr].Tx = 100 * ctr + rand();
S[ctr].Rx = 100 * ctr + rand();
MyKey key(S[ctr].NodeId, S[ctr].Index, S[ctr].Data);
m_Stats.insert(make_pair(key, &S[ctr]));
}
show();
// Test lookup
for (ctr = 0; ctr < 6; ctr++)
{
memset(&tmpS[ctr], 0, sizeof(stats_t));
tmpS[ctr].Data = (char *)malloc(10);
memset(tmpS[ctr].Data, 0, 10);
tmpS[ctr].NodeId = ctr;
tmpS[ctr].Index = 1;
sprintf(Buf, "Test-%d", ctr);
strncpy((char *)tmpS[ctr].Data, Buf, strlen(Buf));
srand(time(NULL));
tmpS[ctr].Tx = 100 * ctr + rand();
tmpS[ctr].Rx = 100 * ctr + rand();
MyKey Lkey(tmpS[ctr].NodeId, tmpS[ctr].Index, tmpS[ctr].Data);
cout << "Looking up: ";
dump(tmpS[ctr]);
it = m_Stats.find(Lkey);
if (it == m_Stats.end() )
{
cout << " Result : Key not found" << endl;
}
else
{
cout << " Result : Key found" << endl;
}
}
for (ctr = 0; ctr < 6; ctr++)
{
free(S[ctr].Data);
free(tmpS[ctr].Data);
}
}
===
Here is the output:
==== Start dump container data =====
Node Id:5 Index:1 Data:Test-5
Node Id:4 Index:1 Data:Test-4
Node Id:3 Index:1 Data:Test-3
Node Id:2 Index:1 Data:Test-2
Node Id:1 Index:1 Data:Test-1
Node Id:0 Index:1 Data:Test-0
==== End dump container data ======
Looking up:
Node Id:0 Index:1 Data:Test-0 Result : Key found
Looking up:
Node Id:1 Index:1 Data:Test-1 Result : Key found
Looking up:
Node Id:2 Index:1 Data:Test-2 Result : Key not found
Looking up:
Node Id:3 Index:1 Data:Test-3 Result : Key not found
Looking up:
Node Id:4 Index:1 Data:Test-4 Result : Key not found
Looking up:
Node Id:5 Index:1 Data:Test-5 Result : Key not found
==
Dec 8, 2011 at 4:33am UTC
Your MyKey::operator< tells std::map that key A is "less than" key B if any of members of A are *not equal* to members of B.
All elements you've inserted have different members, so whenever map compares any two elements x and y, it gets "true" for x<y, and again "true" for y<x. Thus, binary search fails and you're unable to look up most keys..
To see it work, seeing as your index is always the same, replace it with
1 2 3 4
bool operator <(const MyKey& param) const
{
return m_nodeId < param.m_nodeId;
}
(but you may have to extend it later if you expect varying indexes)
There are other problems with this program, but that's the one that directly causes the output you observe.
Last edited on Dec 8, 2011 at 4:37am UTC
Dec 8, 2011 at 6:54am UTC
Thanks so much for the response.
I figured out the problem, wish to post the right code for the benefit of anyone who is a newbie in this area:
bool operator < (const MyKey& param) const
{
if (m_nodeId < param.m_nodeId)
return true;
if (m_nodeId > param.m_nodeId)
return false;
if (m_index < param.m_index)
return true;
if ( (strcmp((const char*)m_data, (const char *)param.m_data) < 0))
return true;
return false;
}
Thank you again for that hint, that really got things moving for me.
Last edited on Dec 13, 2011 at 8:17pm UTC