weirdness with std::map<const char *, int>

L

lada77

All,

Just wondering if one of you very helpful guru's out there could
comment on some odd behaviour I am seeing. I'm betting it is something
obvious but I am not experienced enough to tell right away. Here is my
code snippet and the results that I am seeing:

#include <map>
#include <iostream>
int
main(int argc, char *argv[])
{

string ids;
map<const char *, int> mytest;
ids = "john";
mytest[ids.c_str()] = 0;
ids = "james";
mytest[ids.c_str()] = 1;
map<const char *, int>::iterator it;
const char *id;

for (it=mytest.begin(); it != mytest.end(); ++it) {
cout << "-" << it->first << "-" << it->second << endl;
}

id = "john";
if (mytest.find(id) != mytest.end()) {
cout << "Found john" << endl;
}
id = "james";
if (mytest.find(id) != mytest.end()) {
cout << "Found james" << endl;
}
}

So this just creates a map container and populates it with a couple of
values. The key values are entered as strings converted to const char
* values. Running it, I would expect for it to dump out the contents
of the container and then find the entries. However, when I run it, i
just get the dump of the contents but none of my find() commands are
working.

-john-0
-james-1

So is the string.c_str() function doing something funny that I am not
taking into consideration?

Note I am running rhel4 using
gcc version 3.4.4 20050721 (Red Hat 3.4.4-2)

Thanks in advance.
 
R

roberts.noah

All,

Just wondering if one of you very helpful guru's out there could
comment on some odd behaviour I am seeing. I'm betting it is something
obvious but I am not experienced enough to tell right away. Here is my
code snippet and the results that I am seeing:

#include <map>
#include <iostream>
int
main(int argc, char *argv[])
{

string ids;
map<const char *, int> mytest;
ids = "john";
mytest[ids.c_str()] = 0;
id = "john";
if (mytest.find(id) != mytest.end()) {
cout << "Found john" << endl;
}
So is the string.c_str() function doing something funny that I am not
taking into consideration?

I think it probably has more to do with comparison operators on a char*
comparing address values.

Frankly, I'm surprised it doesn't crash.
 
M

mlimber

All,

Just wondering if one of you very helpful guru's out there could
comment on some odd behaviour I am seeing. I'm betting it is something
obvious but I am not experienced enough to tell right away. Here is my
code snippet and the results that I am seeing:

#include <map>
#include <iostream>

and you need "using namespace std;" if you said:
int
main(int argc, char *argv[])

You don't use argc or argv. You can omit them altogether.
{

string ids;
map<const char *, int> mytest;
ids = "john";
mytest[ids.c_str()] = 0;
ids = "james";
mytest[ids.c_str()] = 1;
map<const char *, int>::iterator it;
const char *id;

First, there's no need to have all your variables declared at the top.
Prefer to declare them only when you need them and then in the smallest
possible scope, and always initialize them when you declare them.

Second, why don't you use a map<string,int>? I suspect that this is
where your problem is. Your map key is a pointer address, not a string,
and so when the map compares keys, it doesn't compare "john" and
"james"; rather it compares 0x8042365 and 0x20340500 (or whatever the
addresses are). If you use std::string that won't happen. Alternately,
you can supply the proper string comparison operator as the third
template parameter (see, e.g., http://www.sgi.com/tech/stl/Map.html).

I would suggest you replace these lines with:

map<string,int> mytest;
mytest["john"] = 0;
mytest["james"] = 1;
for (it=mytest.begin(); it != mytest.end(); ++it) {

Prefer something like:

cout << "-" << it->first << "-" << it->second << endl;
}

id = "john";
if (mytest.find(id) != mytest.end()) {
cout << "Found john" << endl;
}

How about:

if( mytest.find("john") != mytest.end() ) {
id = "james";
if (mytest.find(id) != mytest.end()) {
cout << "Found james" << endl;
}

return 0;

Not strictly necessary, but good form nonetheless.
}

So this just creates a map container and populates it with a couple of
values. The key values are entered as strings converted to const char
* values. Running it, I would expect for it to dump out the contents
of the container and then find the entries. However, when I run it, i
just get the dump of the contents but none of my find() commands are
working.

-john-0
-james-1

So is the string.c_str() function doing something funny that I am not
taking into consideration?

Note I am running rhel4 using
gcc version 3.4.4 20050721 (Red Hat 3.4.4-2)

Thanks in advance.

Cheers! --M
 
L

lada77

Thanks for the quick reply and the code tips. I've gone with strings
and i'm much happier for it.
 
R

roberts.noah

Thanks for the quick reply and the code tips. I've gone with strings
and i'm much happier for it.

99% of the time you will be happier with std::string rather than char*
or char[]. Yes, the later are faster (though not necissarily by much)
but unless your strings are static or absolutely bounded to a
particular size you don't want to have to mess with the problems
exhibited by bad char* or char[] code. Buffer overruns have undefined
behavior and in this case they usually really mean *undefined*...code
breaks in places seemingly totally unrelated sometimes and it can take
hours or days to hunt down. Even when you *think* your strings have an
absolute upper bound don't assume this is so...I myself spent hours
trying to find a problem that turned out to be an overrun because some
developer before me assumed an upper bound that seemed totally
rediqulous but when features changed, the length of the string
increased exponentially.

Most of the time your code will not be hindered in speed by the
std::string "problems" like reallocation and such...if you keep in mind
not to make unnecissary temporaries. The cost vs. benefit of
std::string is way way way weighted on the benefit side.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,280
Latest member
BGBBrock56

Latest Threads

Top