c++ - C++:在开始之前不能寻找向量迭代器
问题描述
我在做一个uva问题uva 10935 throwing cards away,我的代码如下。当我运行它时,它说引发了未处理的异常:读取访问冲突,并且它还显示“在开始之前无法寻找向量迭代器”,我不知道我的代码中的问题在哪里:
#include<vector>
#include<iostream>
using namespace std;
int n;
vector<int> out;
int main() {
freopen("data.txt", "r", stdin);
while (scanf("%d", &n) == 1 && n) {
vector<int> cards;
for (int i = 1; i <= n; i++)cards.push_back(i);
vector<int>::iterator it = cards.begin();
vector<int>::iterator end = cards.end();
while (it != (end-1)) {
out.push_back(*it);
it++;
cards.push_back(*it);
it++;
end++;
}
cout << "Discarded cards: ";
for (int j = 0; j < out.size(); j++) {
if(j!=(out.size()-1))cout << out[j] << ", ";
else cout << out[j] << endl;
}
cout << "Remaining card: " << *it << endl;
}
return 0;
}
解决方案
这里的问题仍然存在于 while() 循环中,您在向量中推送新元素,同时将其旧的“结束”地址作为终端引用。
当一个向量推送一个新元素时,它可能需要将整个数组重新分配到一个新位置。在这种情况下,当您线性增加它时,您所持有的“ end ”引用将变得过时,但推动之后的整个向量可能已经转移到其他地方。
我在您的代码中添加了一些调试行,因此您可以看到这是如何发生的。只需运行输入值为 4 的代码。您会看到“结束”值可能不再与向量的重新分配地址相关(如果发生重新分配,它基本上取决于系统来决定)。
#include<vector>
#include<iostream>
using namespace std;
int n;
vector<int> out;
void printVectorElementAddresses(vector<int> &v){
cout<<"==== Vector Element Addresses ====\n";
for(auto itr = v.begin(); itr != v.end(); itr++)
{
cout<<&(*itr);
if(itr == v.end()-1){
cout<<endl;
}
else{
cout<<" ";
}
}
cout<<endl;
}
void printIteratorAddressWithTag(char* tag, vector<int> :: iterator & it, bool printNewLine){
cout<<tag<<&*it<<"; ";
if(printNewLine){
cout<<endl;
}
}
int main() {
// freopen("data.txt", "r", stdin);
while (scanf("%d", &n) == 1 && n) {
vector<int> cards;
for (int i = 1; i <= n; i++)cards.push_back(i);
vector<int>::iterator it = cards.begin();
vector<int>::iterator end = cards.end();
//print vector addresses after initial pushes are done
printVectorElementAddresses(cards);
while (it != (end-1)) {
printIteratorAddressWithTag("it initial = ", it, false);
out.push_back(*it);
it++;
printIteratorAddressWithTag("it after first increment = ", it, false);
cards.push_back(*it);
it++;
printIteratorAddressWithTag("it after second increment = ", it, true);
printIteratorAddressWithTag("end initially in loop = ", end, false);
end++;
printIteratorAddressWithTag("end after increment = ", end, true);
cout<<"Vector Addresses after a new push"<<endl;
printVectorElementAddresses(cards);
}
cout << "Discarded cards: ";
for (int j = 0; j < out.size(); j++) {
if(j!=(out.size()-1))cout << out[j] << ", ";
else cout << out[j] << endl;
}
cout << "Remaining card: " << *it << endl;
}
return 0;
}
只需更改 while 循环中的逻辑,以在推送发生后跟踪旧的“结束”引用。如果其他逻辑没问题,它应该可以工作。
推荐阅读
- javadoc - 无法在具有 onmethod 属性的 lombok setter/getter 上生成 JavaDoc
- django - Django 如何使用 distinct()
- javascript - 如何将私有变量导出到 javaScript(Node.Js)中的公共变量
- swift - 使用默认 UIImagePickerController 在关闭之前拍摄多张照片而不进行预览 - Swift
- python-3.x - 在这种情况下,cv2.addWeighted 和 numpy mean 有什么区别?
- linux - 从命令行查找 SMBIOS 入口点的地址
- android - Google Analytics 未与服务器通信 - AnalyticsReceiver 未注册或已禁用 - 错误
- unity3d - 如何将 AR 应用到视频直播中?
- reactjs - 如何创建没有任何覆盖的 React Modal?
- python - Python Pandas Dataframe - 如何按年份分组并汇总表中的多个列