2011-01-26 10 views
0

私はAccelerated C++の例を使って作業しています。 問題の1つは、試験に合格した生徒のためのレコードを、生徒というベクトルの先頭にコピーするよう読者に求めています。 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 ++が2回あるので、あなたのコードはすべての奇妙な学生をスキップします。 students.size()が均一でない場合、ループは永遠に進みます。 – Artium

+0

この状態では、ベクトルで生徒を受け取り、条件が一致する場合は_same_生徒をベクトルに挿入します。だから、ベクトルに2回書いたことがあります...おそらく、あなたは '失敗'ベクトルを使う必要があります... –

+0

それを繰り返してベクトルを修正するのは本当に良い考えですか?特に、索引付けを使用して各生徒を理解し、渡す生徒をベクターの先頭に複製すると、ベーコンを保存するために複製された「i ++」に頼っています。それが私だったら私はちょうど2番目のベクトルを使用します。 – sarnold

答えて

0

ループでは、iを2回インクリメントします。その後、

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

そして、このようにそれを使用します:

それはstd::sortにカスタム述語を使用することです行うためのクールな方法

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を2回インクリメントしました。また、ベクタは失敗したと宣言しますが、後で何かをしない限り、ベクタは使用しないでください。さらに、関数内のマクロは、基本的には同じことを2回(「std ::」を除いて)言っています。intを使うだけで、次の人が読みやすく理解しやすくなります。

あなたは:: Stdからremove_ifアルゴリズムを使用することができますが、ファンクタではなく、合格している人を(f_not_grade)を通過していない人たちを返す必要があります
+0

私を助けてくれた皆さん、ありがとうございました。あなたは最も役に立ちました。 –

1

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

それともへの道を見ることができますファンクタ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);帰国生徒。 } –

関連する問題