multimap的erase出错?(C++ Primer 习题10.26)
C++ Primer 习题10.26
编写程序建立作者及其作品的multimap容器,使用find函数在multimap中查找元素,并用erase删除,当要删除的元素不存在时,确保程序能正常工作。
一执行到erase就出错,看了参考,erase的用法没错啊!郁闷了!
Syntax:
#include <map>
void erase( iterator pos );
void erase( iterator start, iterator end );
size_type erase( const key_type& key );
[size=9px]
- C/C++ code
#include <iostream>#include <map>#include <string>using namespace std;int main(){ multimap < string, string > authors; authors.insert(make_pair("aa", "aaaaaaaaaaaaaaaa")); authors.insert(make_pair("aa", "bbbbbbbbbbbbbbbb")); authors.insert(make_pair("aa", "cccccccccccccccc")); authors.insert(make_pair("pp", "000000000000000")); authors.insert(make_pair("pp", "111111111111111")); authors.insert(make_pair("pp", "222222222222222")); authors.insert(make_pair("pp", "333333333333333")); authors.insert(make_pair("pp", "444444444444444")); authors.insert(make_pair("bb", "vvvvvvvvvvvvvvvv")); authors.insert(make_pair("bb", "mmmmmmmmmmmmmmmm")); authors.insert(make_pair("bb", "gggggggggggggggg")); authors.insert(make_pair("bb", "yyyyyyyyyyyyyyyy")); authors.insert(make_pair("aa", "dddddddddddddddd")); authors.insert(make_pair("aa", "****************")); authors.insert(make_pair("aa", "////////////////")); //------------------------------------------------- multimap < string, string > ::iterator it; for (it = authors.begin(); it != authors.end(); ++it) cout << it->first << "\t" << it->second << endl; //-------------------------------------------------- cout << "enter element name which you want to erase: "; string elementNameForDelete; cin >> elementNameForDelete; if (cin && !elementNameForDelete.empty()) { typedef multimap < string, string > ::size_type sz_type; sz_type counts = authors.count(elementNameForDelete); it = authors.find(elementNameForDelete); cout << "\nFound: " << counts << "\t" << elementNameForDelete << endl; for (sz_type cnt = 0; cnt != counts; ++cnt, ++it) { if (it != authors.end()) authors.erase(it);//执行到这里就出错 //cout << it->first <<"\t"<< it->second << endl; } } //--------------------------------------------------- cout << "\nnow elements list: " << endl; it = authors.begin(); for (; it != authors.end(); ++it) cout << it->first << "\t" << it->second << endl; return 0;}[解决办法]
it != authors.end() 是不是越界了
[解决办法]
- C/C++ code
#include <iostream>#include <map>#include <string>using namespace std;int main(){ multimap < string, string > authors; authors.insert(make_pair("aa", "aaaaaaaaaaaaaaaa")); authors.insert(make_pair("aa", "bbbbbbbbbbbbbbbb")); authors.insert(make_pair("aa", "cccccccccccccccc")); authors.insert(make_pair("pp", "000000000000000")); authors.insert(make_pair("pp", "111111111111111")); authors.insert(make_pair("pp", "222222222222222")); authors.insert(make_pair("pp", "333333333333333")); authors.insert(make_pair("pp", "444444444444444")); authors.insert(make_pair("bb", "vvvvvvvvvvvvvvvv")); authors.insert(make_pair("bb", "mmmmmmmmmmmmmmmm")); authors.insert(make_pair("bb", "gggggggggggggggg")); authors.insert(make_pair("bb", "yyyyyyyyyyyyyyyy")); authors.insert(make_pair("aa", "dddddddddddddddd")); authors.insert(make_pair("aa", "****************")); authors.insert(make_pair("aa", "////////////////")); //------------------------------------------------- multimap < string, string > ::iterator it; for (it = authors.begin(); it != authors.end(); ++it) cout << it->first << "\t" << it->second << endl; //-------------------------------------------------- cout << "enter element name which you want to erase: "; string elementNameForDelete; cin >> elementNameForDelete; if (cin && !elementNameForDelete.empty()) { typedef multimap < string, string > ::size_type sz_type; sz_type counts = authors.count(elementNameForDelete); it = authors.find(elementNameForDelete); cout << "\nFound: " << counts << "\t" << elementNameForDelete << endl; //---------------------------------------------- multimap < string, string > ::iterator end=it; while(counts--) end++; authors.erase(it,end); //---------------------------------------------- // for (sz_type cnt = 0; cnt != counts; ++cnt, ++it) // { // if (it != authors.end()) //{ // authors.erase(it);//执行到这里就出错 //} // //cout << it->first <<"\t"<< it->second << endl; // } } //--------------------------------------------------- cout << "\nnow elements list: " << endl; it = authors.begin(); for (; it != authors.end(); ++it) cout << it->first << "\t" << it->second << endl; return 0;}
[解决办法]
- C/C++ code
#include <iostream>#include <map>#include <string>using namespace std;int main(){ multimap < string, string > authors; authors.insert(make_pair("aa", "aaaaaaaaaaaaaaaa")); authors.insert(make_pair("aa", "bbbbbbbbbbbbbbbb")); authors.insert(make_pair("aa", "cccccccccccccccc")); authors.insert(make_pair("pp", "000000000000000")); authors.insert(make_pair("pp", "111111111111111")); authors.insert(make_pair("pp", "222222222222222")); authors.insert(make_pair("pp", "333333333333333")); authors.insert(make_pair("pp", "444444444444444")); authors.insert(make_pair("bb", "vvvvvvvvvvvvvvvv")); authors.insert(make_pair("bb", "mmmmmmmmmmmmmmmm")); authors.insert(make_pair("bb", "gggggggggggggggg")); authors.insert(make_pair("bb", "yyyyyyyyyyyyyyyy")); authors.insert(make_pair("aa", "dddddddddddddddd")); authors.insert(make_pair("aa", "****************")); authors.insert(make_pair("aa", "////////////////")); //------------------------------------------------- multimap < string, string > ::iterator it; for (it = authors.begin(); it != authors.end(); ++it) cout << it->first << "\t" << it->second << endl; //-------------------------------------------------- cout << "enter element name which you want to erase: "; string elementNameForDelete; cin >> elementNameForDelete; authors.erase(elementNameForDelete);//删除拥有该键的所有元素 cout << "\nnow elements list: " << endl; it = authors.begin(); for (; it != authors.end(); ++it) cout << it->first << "\t" << it->second << endl; return 0;}
[解决办法]
[解决办法]
在我的环境下运行程序没有报错,但是逻辑已经不对了,运行结果是不对的;3,4楼的做法是正确的,7楼说得不是很准确,erase(it)之后确实是会把对应元素删掉,但是不是所有的。删掉了一个数据之后,迭代器所指示的数据已经不正确了。
我觉得出现什么结果,也是和编译器的不同而不同。
[解决办法]
这个是STL里面元素删除的一个很容易碰到的问题,循环中 itr ++, erase(itr) 之后也不管itr的事,继续使用。
所有的STL提供的类的erase(itr)之后,itr已经是一个无效的指示器了,再做itr ++ 操作就会有问题,
不过一般list,map,multimap 等 erase 都提供了返回值,返回删除元素后的下一个指示器。
一般不只接在for中写itr ++,如下写:
if( cond )
{
itr = yy.erase(itr);
}
else
{
itr ++;
}
或者 yy.erase(itr ++);
[解决办法]
很显然的迭代器实效的例子
- C/C++ code
// 121.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <iostream>#include <map>#include <string>using namespace std;class AAA{public: static void display1() { printf("display1 is called.\n"); } void display2() { printf("display2 is called.\n"); }};typedef struct FILEINFO { char Sum[100]; char Say[100]; }FileInfo ; int _tmain(int argc, _TCHAR* argv[]){ //// 静态函数指针pFun1 //void (*pFun1)() = &AAA::display1; //pFun1(); // 输出display1 is called. //// 非静态函数指针pFun2 // //void (AAA::*pFun2)()= &AAA::display2; // 此行已编译期报错 //AAA::*pFun2(); // 我想此行输出display2 is called. //AAA a; // ///* //问题一: //如何实现pFun2呢? //*/ multimap < string, string > authors; authors.insert(make_pair("aa", "aaaaaaaaaaaaaaaa")); authors.insert(make_pair("aa", "bbbbbbbbbbbbbbbb")); authors.insert(make_pair("aa", "cccccccccccccccc")); authors.insert(make_pair("pp", "000000000000000")); authors.insert(make_pair("pp", "111111111111111")); authors.insert(make_pair("pp", "222222222222222")); authors.insert(make_pair("pp", "333333333333333")); authors.insert(make_pair("pp", "444444444444444")); authors.insert(make_pair("bb", "vvvvvvvvvvvvvvvv")); authors.insert(make_pair("bb", "mmmmmmmmmmmmmmmm")); authors.insert(make_pair("bb", "gggggggggggggggg")); authors.insert(make_pair("bb", "yyyyyyyyyyyyyyyy")); authors.insert(make_pair("aa", "dddddddddddddddd")); authors.insert(make_pair("aa", "****************")); authors.insert(make_pair("aa", "////////////////")); //------------------------------------------------- multimap < string, string > ::iterator it; for (it = authors.begin(); it != authors.end(); ++it) cout << it->first << "\t" << it->second << endl; //-------------------------------------------------- cout << "enter element name which you want to erase: "; string elementNameForDelete; cin >> elementNameForDelete; if (cin && !elementNameForDelete.empty()) { typedef multimap < string, string > ::size_type sz_type; sz_type counts = authors.count(elementNameForDelete); it = authors.find(elementNameForDelete); cout << "\nFound: " << counts << "\t" << elementNameForDelete << endl; for (sz_type cnt = 0; cnt != counts; ++cnt, ++it) { if (it != authors.end()) it=authors.erase(it);//重新获取迭代器 it-- ;//迭代器回指一步和下次循环的it++抵消,因为 it=authors.erase(it) 一句it获得的是刚刚删除位置的下一位也就是下一个要删除的位置,所以要回指,但这里依然后有遗漏//就是没处理删除的是begin位置的情况,若删除begin回指后超出begin位置会非法,楼主自己再小小的处理下,但是改完之后现在程序除了删除aa都没问题可以测试一下 //cout << it->first <<"\t"<< it->second << endl; } } //--------------------------------------------------- cout << "\nnow elements list: " << endl; it = authors.begin(); for (; it != authors.end(); ++it) cout << it->first << "\t" << it->second << endl; return 0;}