Arani
Arani

Reputation: 400

multimap on C-style string key fails to insert entries

I am trying to create a multimap indexed on a C-style string, as shown in the following code segment:

    #include <cstring>
    #include <map>
    #include <iostream>

    using namespace std;

    int main(void)
    {
        int i, j;
        int (*fn_pt)(const char *, const char *) = strcmp;
        multimap<char *, char *, int (*)(const char *, const char *)>a(fn_pt);

        for (i = 0; i < 2; i++)
        {
            char key[2];
            sprintf(key, "%d", i);
            for (j = 0; j< 5; j++)
            {
                char value[2];
                sprintf(value, "%d", j);
                a.insert(pair<char *, char *>(key, value));
            }
        }

        for (i = 0; i < 2; i++)
        {
            char key[2];
            sprintf(key, "%d", i);
            multimap<char *, char *>::iterator it = a.find(key);
            while (it != a.end())
            {
                cout << it->first << "\t" << it->second <<endl;
                it++;
            }
        }
    }

Simply changing the key in the above program to integer gives me the expected result. But, indexing the multimap on a string is giving me something unexpected (only rows of 1's and 4's separated by space), instead of showing me every value for every key value used.

Where am I going wrong in this?

Thanks

Upvotes: 2

Views: 576

Answers (3)

Andriy
Andriy

Reputation: 8594

strcmp is a wrong predicate to use in multimap. The predicate shall satisfy the following:

The expression comp(a,b), where comp is an object of this comparison class and a and b are key values, shall return true if a is to be placed at an earlier position than b in a strict weak ordering operation.

strcmp violates that because it returns a nonzero value if the strings are unequal, either a < b or a > b.

You should define your own predicate which returns true if and only if the first string is less than the second.

Upvotes: 4

user3458
user3458

Reputation:

You're using the memory of key and value long after they go out of scope. In fact, all your char* pointers point at the same piece of stack memory, and that piece is ready to be reused by the time you actually look at it.

To do what you want you need to use strdup() to create a permanent copy of your char * data. Of course, then you need to worry about deallocating it later.

Upvotes: 1

David Schwartz
David Schwartz

Reputation: 182753

    multimap<char *, char *, int (*)(const char *, const char *)>a(fn_pt);

    for (i = 0; i < 2; i++)
    {
        char key[2];
        sprintf(key, "%d", i);
        for (j = 0; j< 5; j++)
        {
            char value[2];
            sprintf(value, "%d", j);
            a.insert(pair<char *, char *>(key, value));
        }
    }

You're storing two pointers in a container, and then you're destroying the objects (key and value) those pointers point to when they go out of scope. This leaves the container holding information that is now meaningless.

Upvotes: 3

Related Questions