C ++ STL card does not recognize key

I have this code, CBString is just a string class that I use for some processing

char * scrummyconfigure::dosub(strtype input) { CBString tstring; tstring = input; uint begin; uint end; begin = tstring.findchr('$'); end = tstring.findchr('}',begin); CBString k = tstring.midstr(begin+2,end-2); // this is BASE strtype vname = (strtype) ((const unsigned char*)k); strtype bvar = (strtype) "BASE"; assert(strcmp(bvar,vname) == 0); // this never fails // theconf is just a struct with the map subvars // subvars is a map<const char *, const char *> out(theconf->subvars[bvar]); // always comes up with the value out(theconf->subvars[vname]); // always empty uint size = end - begin; tstring.remove(begin, size); return (const char *)tstring; // it OKAY! it got an overload that does things correctly //inline operator const char* () const { return (const char *)data; } <-- this is how it is declared in the header of the library } 

Why does strcmp always say that the strings are the same, but only the variable I declared as bvar returns something?

+4
source share
3 answers

I assume strtype is defined as follows:

 typedef char * strtype 

Your problem is that you assume that vname and bvar have the same value, where in reality they have different values, each of which points to a memory block that contains identical data.

std::map stupidly compares them with ==, and I'm sure you will find that if you compared them with ==, you would get a lie, as expected. Why exactly do you use the std::string class?

Edit: I rewrote your method to be less scary:

 // implied using namespace std; string ScrummyConfigure::removeVariableOrSomething(string tstring) { uint begin; // I'll assume uint is a typedef to unsigned int uint end; begin = tstring.find('$', 0); end = tstring.find('}', begin); string vname = tstring.substr(begin + 2, end - 2); // this is supposedly BASE assert(vname == "BASE"); // this should be true if vname actually is BASE out(this->conf->subvars[bvar]); // wherever theconf used to be, its now a member out(this->conf->subvars[vname]); // of ScrummyConfigure and its been renamed to conf uint size = end - begin; tstring.erase(begin, size); return tstring; // no casting necessary } 
+5
source

// subvars is map<const char *, const char *>

The key of this card is not a string for one, but a memory address. The corresponding check will be

 assert( bvar == vname); 

which is likely to fail. You will need to change the key type to a string class (either std::string or CBString for significant use of the map.

+5
source

Just because the lines are the same, this does not mean that std :: map will treat them as the same key. It depends on the Compare class, which is used by std :: map, which by default is less<KeyType> - which gives the same result as using the less operator.

You can define a class that operator() defines to make a proper comparison with your strtypes types and pass this as your third template argument when defining your std :: map. Or, as suggested, use std :: string as your strtype type.

+5
source

All Articles