设计一段演示程序:打印n个数字,然后指定擦掉其中的某一个,重新打印剩下的数字。
#include <iostream>
#include <vector>
using std::cout;
using std::cin;
using std::endl;
using std::vector;
int main(int argc, char* argv[])
{
const int MAX = 10;
vector<int> v;
for (int i = 0; i < MAX; i++) {
v.push_back(i);
cout << v[i] << '\t';
}
int ers = -1;
while ( ers < 0 || ers >= MAX) {
cout << "Erase No.";
cin >> ers;
}
for (vector<int>::const_iterator i = v.begin(); i != v.end(); i++) {
if (*i == ers) {
v.erase(i);
}
}
for (vector<int>::const_iterator i = v.begin(); i != v.end(); i++) {
cout << *i << '\t';
}
cout << endl;
return 0;
}
这个程序看似没什么错误,可以顺利编译,也可以顺利运行,甚至,大部分情况下可可以正常完成。
我们这里设置的n为10(MAX),事实上,我们擦掉0到8都没有问题,但是,我们要擦掉9的时候,程序却出错了!
在我们遍历查找对等值的循环中,一开始v.end()指向第10个元素(数值为9)的后面一个位置(不存在的第11个元素的位置)。当迭代器指向第10个元素(数值为9)的时候,v.erase()生效运行;下一轮循环中,迭代器本来应该指向第11个元素的位置,并且等于v.end()并结束循环。但是,因为我们擦掉了vector中的一个元素,v.end()指向的是现在的最后一个元素——第9个元素的后面,也就是第10个元素的位置。这样,迭代器到了11,而判断确是其是否到10,这将永远无法实现,形成了一个逻辑bug,所以系统抛出错误了。
一个修正的办法是把需要擦掉的迭代器找出来,在循环结束后再擦掉,下面修改后的程序就可以正常的擦掉9了。
#include <iostream>
#include <vector>
using std::cout;
using std::cin;
using std::endl;
using std::vector;
int main(int argc, char* argv[])
{
const int MAX = 10;
vector<int> v;
for (int i = 0; i < MAX; i++) {
v.push_back(i);
cout << v[i] << '\t';
}
int ers = -1;
while ( ers < 0 || ers >= MAX) {
cout << "Erase No.";
cin >> ers;
}
vector<int>::const_iterator ers_i;
for (vector<int>::const_iterator i = v.begin(); i != v.end(); i++) {
if (*i == ers) {
ers_i = i;
}
}
v.erase(ers_i);
for (vector<int>::const_iterator i = v.begin(); i != v.end(); i++) {
cout << *i << '\t';
}
cout << endl;
return 0;
}
posted on 2010-06-10 11:03
lf426 阅读(1646)
评论(1) 编辑 收藏 引用 所属分类:
语言基础、数据结构与算法