2014-10-10 5 views
0

질문 : 제이는 친구의 커피 잔을 빌려했다은 범위 오류 중

어떻게 든 그것을 잃었다. 친구는 그 사실을 알게되었을 때 매우 화가 나서 Jay는 그의 친구에게 손상을 통제하기 위해 교체 용 찻잔을 사기로 결정했습니다. 불행히도 Jay는 그가 빌린 머그잔의 색깔을 기억하지 않습니다. 그는 단지 색이 흰색, 검정색, 파란색, 빨간색 또는 노란색 중 하나라는 것을 알고 있습니다. 제이 (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

경향이 덜 오류가있는 알고리즘을 사용하는 것이 더 나은. 이것은 종종 여러 가지 문제를 제시하며 그 중 하나는 방금 만났습니다. [지우기 삭제 관용구] (http://en.wikipedia.org/wiki/Erase-remove_idiom)를 조사해야합니다. 이에 대한 좋은 토론은 [this post] (http://stackoverflow.com/questions/347441/erasing-elements-from-a-vector)에서 볼 수 있습니다. – CoryKramer

답변

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'를'remove_if ' '. – CoryKramer

+0

당신이 맞다는 것을 @Cyber가 의심하지만, 나는 이것을 컴파일하지 않을 것이라고 생각한다. (나는'remove_if'가 술어를 필요로한다.) – gsamaras

+0

'std :: remove'는 그렇게 좋을 것이라고 생각한다. 'std :: remove_if'의 서술문에있는 문제는 모든 요소를'color'와 비교하려고한다는 것입니다. – gsamaras

-1

반복 중에 colorVector을 수정하고 있습니다.

색상 중 하나를 제거하면 벡터는 갑자기 4 개 길이의 항목으로 만 표시됩니다. 하드 - 대신 colorVector.size에서 중지함으로써

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

: - 당신은 (삭제하기 전에 할 안전하다고) 5 항목으로 이동하려고 지금 때

이 시도 충돌 을 입력하면 목록이 경계를 벗어나지 않게됩니다.

편집 :
은 건너 뛰고 다음 중 하나

Edit2가 피하기 위해 추가 --i 문 :, 일반적으로 배열 당신 '에서 항목을 제거하는 것은 좋지 상태 아래 댓글
입니다 현재 iterating에서.

+2

벡터를 반복하면서 지울 때마다 크기를 체크하더라도 loop. 물론, 범위를 벗어나지 않지만 일부 요소를 건너 뛸 수 있습니다. –

+0

무언가를 삭제하면'i'를 줄여야합니다. 다른 대답에서 제안 된 기법을 사용하는 것이 더 낫습니다. – gsamaras

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() 
);