C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

querry related to STL map..

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
ravips
Guest





PostPosted: Wed Sep 27, 2006 8:52 pm    Post subject: querry related to STL map.. Reply with quote



I have a map<char *,int> it does not work consistently. I have used
similar sort of implementation as below:

map<char *,int> m1;
map<char *,int>::iterator i;

m1["January"] = 31;
m1["February"] = 28;
m1["March"] = 31;
m1["April"] = 30;
m1["May"] = 31;
m1["June"] = 30;
m1["July"] = 31;

This is similar to the map that i have used. Now accessing this yields
different results as below:

Option1:

char *p = "May";
int it = m1[p]; // Works properly returns 31.

Option2:
char *p = new char[3];
strcpy(p, "May");
int it = m1[p]; // returns 0 .. instead of 31 ....

Can anybody help me to resolve this issue?

Thanks.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Thomas Tutone
Guest





PostPosted: Wed Sep 27, 2006 10:55 pm    Post subject: Re: querry related to STL map.. Reply with quote



ravips wrote:

Quote:
I have a map<char *,int> it does not work consistently. I have used
similar sort of implementation as below:

map<char *,int> m1;
map<char *,int>::iterator i;

m1["January"] = 31;
m1["February"] = 28;
m1["March"] = 31;
m1["April"] = 30;
m1["May"] = 31;
m1["June"] = 30;
m1["July"] = 31;

This is similar to the map that i have used. Now accessing this yields
different results as below:

Option1:

char *p = "May";
int it = m1[p]; // Works properly returns 31.

Option2:
char *p = new char[3];
strcpy(p, "May");
int it = m1[p]; // returns 0 .. instead of 31 ....

Can anybody help me to resolve this issue?

You cross-posted to comp.lang.c++ and received a number of responses
answering your question.

Here's a link to your post and the responses:

http://tinyurl.com/qex8v

Best regards,

Tom


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Thomas Maeder
Guest





PostPosted: Wed Sep 27, 2006 10:58 pm    Post subject: Re: querry related to STL map.. Reply with quote



{ extraneous linebreaks removed. -mod }

"ravips" <ravips123 (AT) gmail (DOT) com> writes:

Quote:
I have a map<char *,int> it does not work consistently. I have used
similar sort of implementation as below:

map<char *,int> m1;
map<char *,int>::iterator i;

m1["January"] = 31;

Side note: The type of "January" is 'array of 8 char const'. The
implicit conversion of a string literal to 'pointer to char'
(non-const!) that this code relies on is deprecated. Better make the
key type of your map char const *.


Quote:
m1["February"] = 28;
m1["March"] = 31;
m1["April"] = 30;
m1["May"] = 31;
m1["June"] = 30;
m1["July"] = 31;

This is similar to the map that i have used. Now accessing this yields
different results as below:

Option1:

char *p = "May";
int it = m1[p]; // Works properly returns 31.

Option2:
char *p = new char[3];
strcpy(p, "May");

This copies 4 char objects to an array that can only hold 3 char
objects. Your program has undefined behavior.


Quote:
int it = m1[p]; // returns 0 .. instead of 31 ....

That's one instance of undefined behavior.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Harald Luessen
Guest





PostPosted: Wed Sep 27, 2006 10:59 pm    Post subject: Re: querry related to STL map.. Reply with quote

On 27 Sep 2006 "ravips" wrote:

Quote:
Option2:
char *p = new char[3];
strcpy(p, "May");
int it = m1[p]; // returns 0 .. instead of 31 ....

Can anybody help me to resolve this issue?

Why do you believe that the 4 chars of "May"
fit in the 3 chars of p[]?

Harald


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
RenjithMohan
Guest





PostPosted: Wed Sep 27, 2006 11:24 pm    Post subject: Re: querry related to STL map.. Reply with quote

Quote:
char *p = new char[3];
Here you are wrong. In order to have "May" you need size 4 to

accomodate the null terminator.
Quote:
strcpy(p, "May");
int it = m1[p]; // returns 0 .. instead of 31 ....

Basically your comparator for the map is wrong. string literals have
the same type and may be ordered according to the < operator. For char*
, the default less<> comparator is no longer acceptable..

The correct way to order the keys, if it is char* is to have a custom
comparator for the map.

template<class _Ty>
struct comp_function
: public binary_function<_Ty, _Ty, bool>
{ // functor for operator<
bool operator()(const _Ty& _Left, const _Ty& _Right) const
{ // apply strcmp to operands
return (strcmp(_Left, _Right)< 0);
}
};

//Notice how we have given our comparator
map<char *,int, comp_function<char*> > m1;
map<char *,int, comp_function<char*> >::iterator i;

m1["January"] = 31;
m1["February"] = 28;
m1["March"] = 31;
m1["April"] = 30;
m1["May"] = 31;
m1["June"] = 30;
m1["July"] = 31;

Now the second example(as well as the first) yields the correct result.
char *p = new char[4];
strcpy(p, "May");
int it = m1[p]; //now gives 31.





Quote:

Can anybody help me to resolve this issue?

Thanks.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Pete Becker
Guest





PostPosted: Thu Sep 28, 2006 12:27 am    Post subject: Re: querry related to STL map.. Reply with quote

ravips wrote:
Quote:
I have a map<char *,int> it does not work consistently. I have used
similar sort of implementation as below:


You've gotten several replies poining out that the code opies too many
characters into the allocated array. That's true, and that's a potential
problem, but it's not the cause of the match failures. The problem is
that map doesn't do anything special with a char* key. That is, two such
keys are equal if the values of the pointers are the same. So when the
code copies "May" into an allocated array, the address of that copy is
different from the address of the original, and the two keys do not
match. Further, there's no guarantee that two string literals with the
same text (i.e. "May" and "May") will have the same address, so it was
just luck that the first version of the code seemed to work.

The solution is to either provide a comparator object that calls strcmp
to compare two char*s for equality, or to use std::string instead of
char*. The latter is simpler.

--

-- Pete

Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." For more information about this book, see
www.petebecker.com/tr1book.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
kanze
Guest





PostPosted: Thu Sep 28, 2006 6:31 pm    Post subject: Re: querry related to STL map.. Reply with quote

Thomas Maeder wrote:

Quote:
"ravips" <ravips123 (AT) gmail (DOT) com> writes:

I have a map<char *,int> it does not work consistently.

It does. You just don't like the semantics it has.

Quote:
I have used similar sort of implementation as below:

map<char *,int> m1;

I can think of very, very few cases where this map might make
sense. Do you really want to map addresses to int's?

More likely, you want to map C-style strings to ints (judging
from the code which follows). In that case:

1. you need to provide a comparison function or functional
object, with its type as the third instantiation argument of
map, and

2. you need to do something to ensure that no one modifies the
C style string once it is in the map---using char const* is
the easiest solution.

In practice, I generally find it a lot easier to just map
std::string to whatever. That takes care of all of the above
issues, plus any memory management issues which crop up using
the map.

Quote:
map<char *,int>::iterator i;

m1["January"] = 31;

Side note: The type of "January" is 'array of 8 char const'.
The implicit conversion of a string literal to 'pointer to
char' (non-const!) that this code relies on is deprecated.
Better make the key type of your map char const *.

Agreed, but I think you'd agree that making it std::string would
be even better.

Quote:
m1["February"] = 28;
m1["March"] = 31;
m1["April"] = 30;
m1["May"] = 31;
m1["June"] = 30;
m1["July"] = 31;

This is similar to the map that i have used. Now accessing
this yields different results as below:

Option1:

char *p = "May";
int it = m1[p]; // Works properly returns 31.

Whether it returns 0 or 31 is not specified. The implementation
may merge identical string literals or not. And since the index
is the address of the data, and not the data itself, you get
different results depending on whether the string literals have
been merged or not.

Quote:
Option2:
char *p = new char[3];
strcpy(p, "May");

This copies 4 char objects to an array that can only hold 3
char objects. Your program has undefined behavior.

int it = m1[p]; // returns 0 .. instead of 31 ....

That's one instance of undefined behavior.

Actually, even correcting the undefined behavior (which isn't
actually likely to cause a problem in the case of "May", because
most memory allocators cannot allocated an odd number of bytes
exactly, and round up), the standard requires 0 here. There's
no way that the string literal used to initialize the entry
could possibly have the same address as dynamically allocated
memory.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
kanze
Guest





PostPosted: Thu Sep 28, 2006 6:32 pm    Post subject: Re: querry related to STL map.. Reply with quote

RenjithMohan wrote:
Quote:
char *p = new char[3];
Here you are wrong. In order to have "May" you need size 4 to
accomodate the null terminator.
strcpy(p, "May");
int it = m1[p]; // returns 0 .. instead of 31 ....

Basically your comparator for the map is wrong. string
literals have the same type and may be ordered according to
the < operator. For char*, the default less<> comparator is
no longer acceptable..

The correct way to order the keys, if it is char* is to have a
custom comparator for the map.

template<class _Ty
struct comp_function
: public binary_function<_Ty, _Ty, bool
{ // functor for operator
bool operator()(const _Ty& _Left, const _Ty& _Right) const
{ // apply strcmp to operands
return (strcmp(_Left, _Right)< 0);
}
};

Just one question: why on earth do you make this a template,
since it will fail to instantiate unless _Ty is char* or char
const*?j

Quote:
//Notice how we have given our comparator
map<char *,int, comp_function<char*> > m1;

And there is still one problem left:

m1.begin()[ 0 ] = 'z' ;

Looks fine to me, and the compiler won't complain. But
supposing the initializations below, I rather doubt that
m1["zanuary"] will return 31 after this.

The obvious solution is to simply write:

map< std::string, int > m1 ;

and be done with it. If you really insist on C style strings,
then at the very least:

map< char const*, int, comp_function > m1 ;

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.