2017-03-07 71 views
-2

我正在制作一个程序只是为了练习向量,这让我很难过。该计划的重点是制作比赛来帮助人们在餐馆之间进行选择。pop_back()导致“向量下标超出范围”

下面是导致错误的代码:

#include <iostream> 
#include <vector> 
#include <string> 

const int ITEMS_PER_MATCHUP = 2; 

using namespace std; 

int PromptChoice(string first, string second, string helpMessage = "") { 
    string input; 
    while (true) { 
     cout << "Which restaurant do you prefer, " << first << "(1) or " << second << "(2)? "; 
     cin >> input; //no need to protect as it is going into a string variable 
     if (input == "first" || input == "1" || input == "left" || input == "First" || input == "Left") { 
      return 0; 
     } 
     else if (input == "second" || input == "2" || input == "right" || input == "Second" || input == "Right") { 
      return 1; 
     } 
     // if the response was not recognized 
     else cout << endl << helpMessage << endl << "Please enter 1 or 2" << endl << "Please try again." << endl << endl; 
    } 
} 

int main() { 
    vector<string> list = { "Burger Place", "Italian Place", "Soup And Salad Place", "BBQ Place" }; 

    vector<int> stillInTheRunning; 
    for (int index = 0; index < list.size(); index++) { //populates an array full of values 0 to the size of the array 
     stillInTheRunning.push_back(index); 
    } 

    int matchupsThisRound = stillInTheRunning.size(); 

    for (int i = 0; i < matchupsThisRound; i += ITEMS_PER_MATCHUP) { //ITEMS_PER_MATCHEP == 2 

     int choice = PromptChoice(list[stillInTheRunning[i]], list[stillInTheRunning[i + 1]]); 
     //stillInTheRunning.erase(stillInTheRunning.begin() + i + choice); 
     stillInTheRunning.pop_back(); 

    } 

    for (int i = 0; i < stillInTheRunning.size(); i++) { //print the vector 
     cout << endl << stillInTheRunning[i] << endl; 
    } 

    system("pause"); //I know I know don't use system. just for debuging? 
} 

如果我没有理解错误通常,当您试图访问一个矢量索引超出范围发生。大于vector.size() - 1但在这种情况下,它发生在我尝试使用时vector.erase()

想到也许我只是抢夺for循环我试图切换到pop_back(),因为我认为你不能搞砸那一个。但我仍然有错误。

玩弄它我试着评论一些事情。

一样,如果我注释掉提示功能:

for (int i = 0; i < matchupsThisRound; i += ITEMS_PER_MATCHUP) { //ITEMS_PER_MATCHEP == 2 
     //int choice = PromptChoice(list[stillInTheRunning[i]], list[stillInTheRunning[i + 1]]); 
     //stillInTheRunning.erase(stillInTheRunning.begin() + i + choice); 
     stillInTheRunning.pop_back(); 
    } 

没有错误

如果我注释掉pop_back():

for (int i = 0; i < matchupsThisRound; i += ITEMS_PER_MATCHUP) { //ITEMS_PER_MATCHEP == 2 
     int choice = PromptChoice(list[stillInTheRunning[i]], list[stillInTheRunning[i + 1]]); 
     //stillInTheRunning.erase(stillInTheRunning.begin() + i + choice); 
     //stillInTheRunning.pop_back(); 
    } 

也没有错误。

是什么导致问题?

+0

'vector <> :: pop_back()'从vector中移除最后一个元素,'vector <> :: erase()'显式定位一个或多个元素。但是,这两种方法都要求“已解决”的元素之前已经存在。在调试器中查看大小元素之前包含的内容,或者在移除之前仅调用vector的cout size()。 – Scheff

+0

是的,我看着那个。错误发生时的大小是4 –

+0

您是否考虑过这个问题:每次,您使用'vector <> :: erase()'以及某些'begin()+ i',以下所有元素都会向前移动一步。因此'i'正在增加,但'size()'正在减小。在迭代的“中间”,“i”比size()更大。以这种方式从向量中移除最好从后到前完成。 – Scheff

回答

2

我发现它!

其这里

PromptChoice(list[stillInTheRunning[i]], list[stillInTheRunning[i + 1]]) 

上的for循环的第二次运行I = 2; 从背面弹出一个项目后,矢量的大小现在是3而不是4,所以stillInTheRunning [i + 1]试图获取索引3中现在不存在的项目。

0

问题是,当你pop_backstillInTheRunning跌幅大小,但matchupsThisRound保持不变,所以最终循环到达那里i+1超出stillInTheRunning的范围内的点。

另外有点奇怪,你在每个周期增加i 2,但pop_back只有一次。