Я пытаюсь создать мультикарту, проиндексированную на строку в стиле C, как показано в следующем фрагменте кода:
#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++;
}
}
}
Простое изменение ключа в приведенной выше программе на целое дает мне ожидаемый результат. Но индексация мультикарты в строке дает мне нечто неожиданное (только строки 1 и 4, разделенные пробелом), вместо того, чтобы показывать мне каждое значение для каждого используемого значения ключа.
Куда я в этом ошибаюсь?
Спасибо
strcmp
неверный предикат для использования в multimap
,
Предикат должен удовлетворять следующему:
Выражение comp (a, b), где comp является объектом этого класса сравнения, а a и b являются ключевыми значениями, должно возвращать true, если a нужно поместить в более раннюю позицию, чем b, в операции строгого слабого упорядочения.
strcmp
нарушает это, потому что он возвращает ненулевое значение, если строки неравны, либо < б или а> б.
Вы должны определить свой собственный предикат, который возвращает true
если и только если первая строка меньше второй.
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));
}
}
Вы храните два указателя в контейнере, а затем уничтожаете объекты (key
а также value
) эти указатели указывают на то, когда они выходят из области видимости. Это оставляет контейнер, содержащий информацию, которая теперь не имеет смысла.
Вы используете память о key
а также value
долго после того, как они выходят за рамки. На самом деле, все ваши char*
указатели указывают на один и тот же фрагмент стековой памяти, и этот фрагмент готов к повторному использованию к тому времени, когда вы на самом деле посмотрите на него.
Чтобы делать то, что вы хотите, вы должны использовать strdup()
создать постоянную копию вашего char *
данные. Конечно, тогда вам нужно побеспокоиться об освобождении его позже.