0

Can someone please help me understand this?

I have created a map of char strings as key and int as a value from a two dimensional char array. I see duplicate entries being inserted in the map!

To test further, I added two char strings of the same value to a map (also in the code, commented), and only one of them was added.

void countstr(char words[][NUM_OF_STR])
{
    map<char*, int> mwords;

    cout<<"ORIG"<<endl;
    for(int i = 0; i < NUM_OF_STR; i ++)
    {
        cout<<words[i]<<endl;
        mwords.insert(pair<char*, int>(words[i], 0));
        cout<<mwords.size()<<endl;
    }

    map<char*, int>::iterator itr;

    cout<<endl<<"MAP"<<endl;
    for(auto i = mwords.begin(); i != mwords.end(); i ++)
    {
        cout<<i->first<<"\t"<<i->second<<endl;
    }

    return;
}

int main()
{
    char words[NUM_OF_STR][5] = { "abc", "pqr", "xyz", "abc", "pqr" };

    /*map<char*, int> mwords;
    mwords.insert(pair<char*, int>("abc", 1));
    cout<<mwords.size()<<endl;
    mwords.insert(pair<char*, int>("abc", 2));
    cout<<mwords.size()<<endl;*/

    countstr(words);
    return 0;
}

Output:

ORIG
abc
1
pqr
2
xyz
3
abc
4
pqr
5

MAP
abc     0
pqr     0
xyz     0
abc     0
pqr     0
  • "Map allowing duplicates" - that would be a `std::multimap` (*or* a `std::map` holding a type with a broken `operator<` - remember, your tyoes need to implement a *strict weak ordering* for `map` to do the right thing). – Jesper Juhl Jan 15 '19 at 18:44

1 Answers1

5

If you compare words[0] and words[3] you'll see that they are not the same. That's because they're pointers, so the operators ==, < etc will be looking at the addresses of your C strings, not the contents.

Since their contents are the same, it is possible — but not guaranteed — that their addresses will be the same too (this is a fact of life with string literals). In your case they're not the same, so the keys are logically distinct and both elements are accepted.

Pointers are not containers.

You can make the map use strcmp instead by providing a custom comparator, or you can just use std::string (or std::string_view) for your keys. :)

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • Alternative, `std::string_view`. Assuming there are no lifetime-issues in the real code. For giggles, one could also use `std::less` as the comparator. – Deduplicator Jan 15 '19 at 18:33
  • @Deduplicator Good idea! – Lightness Races in Orbit Jan 15 '19 at 18:33
  • So, the commented map insert statements with literal “abc” string could also be allowed, if the compiler decides to treat them as two separate strings (even though their contents are the same)? – Rakesh Mhasawade Jan 15 '19 at 18:38
  • @RakeshMhasawade Stop thinking about strings, you don't have strings, you have pointers. The issue is whether the compiler uses the same pointer for two string literals with the same contents. The simple answer of course is to start using real strings `map mwords;`. – john Jan 15 '19 at 19:52
  • @RakeshMhasawade Yes. – Lightness Races in Orbit Jan 16 '19 at 00:42