2011-01-26 4 views
0

Accelerated C++의 예제를 진행하고 있습니다. 문제 중 하나는 학생들에게 시험이라고 불리는 벡터의 시작 부분에 시험에 합격 한 학생의 기록을 복사 해달라고 요청합니다. fgrade은 실패한 학생을 반환하는 다른 곳에서 정의 된 함수입니다. 그런 다음 resize 함수를 사용하여 학생으로부터 추가 요소를 제거해야하므로 전달하는 요소 만 포함됩니다. 이 코드를 시도했지만 작동하지 않습니다. 오류가 아래 코드에있는 경우 누군가에게 알려 주시겠습니까?벡터에 요소를 삽입하는 것에 관한 C++ 질문

#include "stdafx.h" 
#include <vector> 
#include "Student_info.h" 
#include "grade.h" 

using std::vector; 

// second try: correct but potentially slow 
vector<Student_info> extract_fails(vector<Student_info>& students) 
{ 
    vector<Student_info> fail; 
#ifdef _MSC_VER 
    std::vector<Student_info>::size_type i = 0; 
    std::vector<Student_info>::size_type count = 0; 
#else 
    vector<Student_info>::size_type i = 0; 
    vector<Student_info>::size_type count = 0; 
#endif 

    while (i != students.size()) { 
     if (!fgrade(students[i])) { 
      students.insert(students.begin(), students[i++]); 
      count++; 
     } 
     i++; 
    } 
    students.resize(count); 
    return students; 
} 
+0

루프에서 i ++를 두 번 사용하면 코드가 이상한 모든 학생을 건너 뜁니다. students.size()가 짝수가 아니면 반복문은 영원히 사라질 것입니다. – Artium

+0

이 상태에 있으면 벡터에서 학생을 데리고 조건이 일치하면 _same_ 학생을 벡터에 삽입합니다. 그래서 벡터에 두 번 있습니다 ... 아마도 '실패'벡터를 사용해야 할 것입니다 ... –

+0

반복해서 벡터를 수정할 수 있습니까? 특히 각 학생을 빠져 나가기 위해 색인 생성을 사용하고 있기 때문에, 지나가는 학생을 벡터의 시작 부분에 복제하면, 베이컨을 저장하기 위해 복사 된 'i ++'에 의존하게됩니다. 그것이 나라면 두 번째 벡터를 사용합니다. – sarnold

답변

0

루프에서 두 번 증가한 숫자는 i입니다.

std::sort에 대한 사용자 정의 술어를 사용하는 것입니다 할 수있는 멋진 방법 :이 같은

bool CompareStudentsByFailure(const Student_info & left, 
           const Student_info & right) { 
    return fgrade(left) > fgrade(right); 
} 

그리고 사용은 :

std::sort(students.begin(), students.end(), CompareStudentsByFailure); 
students.resize(std::distance(students.begin(), 
       std::find_if(students.rbegin(), 
          students.rend(), fpgrade).base())); 

그러나, Jon`s answer 조금 더 간단합니다.

0

Space_C0wb0y와 Artium이 지적했듯이 i를 두 번 증가 시켰습니다. 또한 벡터가 실패했다고 선언하지만 나중에 사용하지 않는 한 벡터를 사용하지 마십시오. 또한 함수의 매크로는 과도한 것처럼 보입니다. 기본적으로 두 번 똑같은 것을 말하고 ("std ::"를 뺀다) int를 사용하면 다음 사람이 읽고 이해하기가 더 쉬울 수도 있습니다.

+0

나를 도와 주신 모든 분들께 진심으로 감사드립니다. 당신이 가장 도움이되었습니다. –

1
대신에이 사람들이 통과 당신은 표준 : 알고리즘에서 remove_if 사용할 수 있지만 펑터가 통과하지 않은 사람 (f_not_grade)를 반환해야

:

std::remove_if(students.begin(), students.end(), f_not_grade) 

을 또는 당신이가는 길을 볼 수 functor here 또는 here을 무효로하면 f_grade 함수를 수정하지 않고 remove_if를 사용할 수 있습니다.

컨테이너를 사용하는 대부분의 작업은 STL에서 구현되므로 언어의 힘을 사용하십시오!. 이런 종류의 함수를 찾으려면 잠시 시간을내어 코드 작성의 어려움을 줄일 수 있습니다.

잘못된 "()"을 삭제하도록 편집되었습니다.

+0

그는 여전히 크기를 조정해야하지만, 문제가되지 않아야합니다. 새로운 시퀀스의 길이를 계산하기 위해'remove_if '에 의해 반환 된 반복자를 사용할 수 있습니다. 이것은 내 솔루션보다 더 우아합니다. –

+0

미안하지만, 나는 부정확했다. fgrade는 학생의 실패 여부를 나타내는 부울을 반환합니다. 위의 마지막 매개 변수로 fgrade() 사용하여 시도했지만이 실패하고 있습니다. 마찬가지로 fgrade == false; 나는이 마지막 코멘트가 어리석은 것처럼 보일 것이다라는 것을 알고있다. 그러나 나는 정말로 여기에서 붙이게된다. Accelerated C++의 책은 훌륭하지만 실제로 우리 중 일부에게는 어려운 예제입니다. –

+0

저자가 insert()와 resize()를 사용하기를 바랍니다.나는 다음과 같이 다시 썼다. 학생들을 패스라는 벡터에 넣었습니다. 이 프로그램은 실행되지만 실패한 모든 학생들을 제거하기 위해 벡터의 크기를 조정하지 않습니다. while (i! = students.size()) {if (! fgrade (students [i])) {pass.push_back (students [i]); 카운트 ++; } else ++ i; } students.insert (students.begin(), pass.begin(), pass.end()); students.resize (count); 귀환 학생; } –

관련 문제