Как заменить <ключ, значение> в мультикарте STD
Перефразируя вопрос - Перефразированный вопрос - у меня есть требование, где мне нужно заменить пару новым ключом и значением. Учти это -
#include <map>
#include <string>
#include <iostream>
using namespace std;
int main()
{
std::multimap<unsigned int, std::string> mymap;
mymap.insert(std::multimap<unsigned int, std::string>::value_type(0, "A1"));
mymap.insert(std::multimap<unsigned int, std::string>::value_type(0, "A2"));
mymap.insert(std::multimap<unsigned int, std::string>::value_type(2, "C1"));
mymap.insert(std::multimap<unsigned int, std::string>::value_type(2, "C2"));
mymap.insert(std::multimap<unsigned int, std::string>::value_type(1, "B1"));
mymap.insert(std::multimap<unsigned int, std::string>::value_type(1, "B2"));
mymap.insert(std::multimap<unsigned int, std::string>::value_type(1, "B3"));
std::pair<std::multimap<unsigned int, std::string>::iterator, std::multimap<unsigned int, std::string>::iterator> pr = mymap.equal_range(1);
std::multimap<unsigned int, std::string>::iterator it;
for (it=pr.first; it!=pr.second; ++it)
{
unsigned int key = it->first;
key = key+10;
std::string val = it->second;
val = "X" + val;
mymap.erase(it);
mymap.insert(std::multimap<unsigned int, std::string>::value_type(key, val));
}
for ( it=mymap.begin() ; it != mymap.end(); it++ )
{
cout << (*it).first << " => " << (*it).second << endl;
}
return 0;
}
Программа аварийно завершает работу в Visual Studio 2008, поскольку итератор признан недействительным.
Я ожидаю, что это будет:
0 => A1
0 => A2
2 => C1
2 => C2
11 => XB1
11 => XB2
11 => XB3
Идея в том, что я хочу заменить существующую запись на карте новой.
Что я делаю неправильно? Любая помощь очень ценится.
2 ответа
Хитрость заключается в том, чтобы сначала продвинуть итератор, а затем стереть копию итератора.
std::multimap<unsigned int, std::string>::iterator it = pr.first;
while (it != pr.second)
{
unsigned int key = it->first;
key = key+10;
std::string val = it->second;
val = "X" + val;
std::multimap<unsigned int, std::string>::iterator itCopy = it;
++it;
mymap.erase(itCopy);
mymap.insert(std::multimap<unsigned int, std::string>::value_type(key, val));
}
В C++11 вы можете сделать это:
std::multimap<unsigned int, std::string>::iterator it = pr.first;
while (it != pr.second)
{
unsigned int key = it->first;
key = key+10;
std::string val = it->second;
val = "X" + val;
it = mymap.erase(it);
mymap.insert(std::multimap<unsigned int, std::string>::value_type(key, val));
}
Кстати, поскольку этот код увеличивает ключ каждый раз, он будет обрабатывать каждый элемент снова и снова.
Если вы удалите запись, где находится итератор, все ссылки на остальную часть мультикарты могут быть потеряны.
(новое) решение:
Просто сделайте "стереть" после того, как вы вставили новые записи:
std::multimap<unsigned int, std::string>::iterator it;
for (it=pr.first; it!=pr.second; ++it)
{
unsigned int key = it->first;
key = key+10;
std::string val = it->second;
val = "X" + val;
mymap.insert(std::multimap<unsigned int, std::string>::value_type(key, val));
}
mymap.erase(pr.first, pr.second);