2014-10-10 150 views
0

的问题是:超出范围的错误

杰伊借了朋友的咖啡杯和莫名其妙地失去了它。由于他的朋友在发现这件事情时会非常生气,Jay决定向他的朋友购买一个替换杯以试图控制损害。 不幸的是,杰伊不记得他借来的杯子的颜色。他只知道颜色是白色,黑色,蓝色,红色或黄色之一。杰伊绕着他的办公室问他的同事他们是否能够回忆起这种颜色,但他的朋友们似乎也不记得杯子的颜色。他们所知道的是杯子的颜色绝对不是。 根据这些信息,帮助Jay弄清楚杯子的颜色是什么。

的办法,我要去一下:我创造的所有可能的颜色矢量

:白色,黑色,蓝色,红色或黄色。然后要求用户输入他将询问的同事人数。然后采取颜色建议,并为每个条目我比较它与矢量。如果它在那里,我会弹出颜色。最终只有一种颜色会留在向量中,这是失去的杯子的颜色。

我的问题:

我得到一个出界错误输入第一个颜色后,我无法找出原因。确切的错误是:

terminate called after throwing an instance of 'std::out_of_range' 
what(): vector::_M_range_check 
Abort (core dumped) 

我的代码是:

 #include <iostream> 
     #include <string> 
     #include <algorithm> 
     #include <climits> 
     #include <stdio.h> 
     #include <vector> 

     using namespace std; 

     int main(int argv, char* argc[]) 
     { 
      string color; 
      vector<string> colorVector; 

      colorVector.push_back("White"); 
      colorVector.push_back("Black"); 
      colorVector.push_back("Blue"); 
      colorVector.push_back("Red"); 
      colorVector.push_back("Yellow"); 

      int numColleagues; 

      cout<< "Please enter the number of Colleagues" << endl; 
      cin >> numColleagues; 

      cout<< "Please enter each suggested color" << endl; 

      int counter = 0; 
      while (counter < numColleagues) { 
      getline(cin, color); 
      counter++; 

       for (int i = 0; i < 5; i++) { 
        if (colorVector.at(i) == color) { 
         colorVector.erase(colorVector.begin() + i); 
        } 
       } 
      } 
      return 0; 
     } 
+1

您正在尝试为你通过它迭代从你的载体删除元素的算法。这通常会带来很多问题,其中之一就是你遇到的问题。你应该调查[erase-remove idiom](http://en.wikipedia.org/wiki/Erase-remove_idiom)。你可以看看[这篇文章](http://stackoverflow.com/questions/347441/erasing-elements-from-a-vector)进行良好的讨论。 – CoryKramer 2014-10-10 18:17:48

回答

1

你擦掉你的向量的元素,但你要访问的所有五行(循环从0到5) 。因此,假设您先删除第一个,然后尝试访问位置4处的元素。超出范围!

所以你的循环改成这样:

colorVector.erase(std::remove(colorVector.begin(), 
           colorVector.end(), color), colorVector.end()); 

更多erase-remove idiom

+0

如果你要实现擦除删除习惯用法,你不需要保留'for'循环,也不需要保留'if'块。字面上只有一行'colorVector.erase(std :: remove_if(colorVector.begin(),colorVector.end(),color),colorVector.end());'是必需的(注意我用'remove_if '。 – CoryKramer 2014-10-10 18:30:10

+0

我怀疑你是对的@Cyber​​。但是,我认为这不会编译。我正在测试...(我的意思是'remove_if'需要一个谓词)。 – gsamaras 2014-10-10 18:32:40

+0

我认为'std :: remove'会很好。'std :: remove_if'的谓词问题是我们想要用'color'比较每个元素。 – gsamaras 2014-10-10 18:42:45

-1

在迭代过程中,您正在修改colorVector

只要删除其中一种颜色,矢量突然只有4个项目的长度。现在,当你试图去第五项(这是安全的删除前做) - 它崩溃

试试这个:在colorVector.size

for (int i = 0; i < colorVector.size(); i++) { 
    if (colorVector.at(i) == color) { 
     colorVector.erase(colorVector.begin() + i); 
     --i; 
    } 
} 

通过停止而不是硬的编码为确保您的列表永远不会超出界限。

编辑:
新增--i声明,以避免跳过下一个

EDIT2:
如下状态的评论,它一般是一个坏主意,从数组你”删除项目目前正在迭代。

+2

即使你每次都检查大小,在迭代时从一个矢量中擦除也是一个坏主意当然,你不会跳出界限,但你可以跳过一些元素 – 2014-10-10 18:38:37

+0

如果你删除了某些东西,你应该减少i,最好使用其他答案中建议的技巧。 – gsamaras 2014-10-10 18:49:55

0

当您调用vector::erase时,它将返回一个迭代器,指向擦除元素后面元素的新位置。因此,如果我们删除这个元素:

1 2 3 4 5 6 
    ^

我们的迭代器会自动更新,以点到5。所以我们不必再递增迭代器,它已经有点递增。考虑到这一点:

auto it = colorVector.begin(); 
for (; it != colorVector.end(); /* do not increment it */) 
{ 
    if (*it == color) 
    { 
     it = colorVector.erase(it); // erase and update 
    } 
    else 
    { 
     ++it; // just update 
    } 
} 

当然更好,只需使用这是不太容易出错

colorVector.erase(
    std::remove(colorVector.begin(), colorVector.end(), color), 
    colorVector.end() 
);