By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,308 Members | 2,141 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,308 IT Pros & Developers. It's quick & easy.

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

P: n/a
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.

Jan 5 '06 #1
Share this Question
Share on Google+
4 Replies


P: n/a

la****@yahoo.com wrote:
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.

Jan 5 '06 #2

P: n/a
la****@yahoo.com wrote:
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>
You're missing <string>, and you need "using namespace std;" if you
don't want to qualify your names below.
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:

typedef map<string, int>::const_iterator CI;
for( CI 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;
}
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

Jan 5 '06 #3

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

Jan 5 '06 #4

P: n/a

la****@yahoo.com wrote:
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.

Jan 5 '06 #5

This discussion thread is closed

Replies have been disabled for this discussion.