Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ STL map not recognizing key

Tags:

c++

map

stl

I have this code, CBString is just a string class 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's OKAY! it's 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 is it that the strcmp always says the strings are the same, but only the variable I declared as bvar returns anything?

like image 790
alexmherrmann Avatar asked Dec 06 '22 13:12

alexmherrmann


2 Answers

I'm assuming strtype is defined in the following way:

typedef char * strtype

Your issue is that you're assuming that vname and bvar have the same value, where in reality, they have different values that each point to a block of memory that contains identical data.

std::map is dumbly comparing them with ==, and I bet you'd find that if you compared them with ==, you would get false, as expected. Why exactly arent you using 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
}
like image 121
Wug Avatar answered Dec 09 '22 15:12

Wug


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

The key of this map isn't a string per-say, but a memory address. The corresponding check would be

assert( bvar == vname);

which will probably fail. You'll need to change the key type to a string class (either std::string or CBString to meaningfully use the map.

like image 35
Luchian Grigore Avatar answered Dec 09 '22 15:12

Luchian Grigore