1

私の remove_if は、除外されていない要素を除外された要素の値で上書きしているようです。これらのコードの目的は、ユーザーが特定のカテゴリの教師のみをフィルターして表示できるようにすることです。(要素を削除していません)コードの一部を次に示します

static string compare;
static string debug;

bool filter_Cat (Teacher &t) 
{ 
    return (t.getCat() != compare); 
}

void filterCat (vector<Teacher> &t)
{
   vector<Teacher>::iterator i;
   vector<Teacher>::iterator newedited = remove_if(t.begin(), t.end(), filter_Cat);
   for (i = t.begin(); i != newedited; ++i)
   {
     Teacher& te = *i;
     te.getName();
     cout << "\t";
     te.getCategory();
     cout << "\t";
     te.getLocation();
   }
 }

 void filterTutorCat(vector<Teacher> &t)
 {
    int choice;
    cout << "No\tCategory" << endl
         << "1\tEnglish" << endl
         << "2\tMath" << endl
         << "3\tScience" << endl
         << "Choose the category you wish to filter :";
    cin >> choice;
    getline(cin, debug);

    if(choice <= 3 && choice > 0)
    {
        if (choice == 1)
        {
          compare = "English";
          filterCat(t);
        }
        if (choice == 2)
        {
          compare = "Math";
          filterCat(t);
        }
        if (choice == 3)
        {
          compare = "Science";
          filterCat(t);
        }

    }
    else
    {
        cout << "Invalid Option" << endl;
    }
 }
4

2 に答える 2

2

remove_if比較関数がfalseを返す要素を右から左にシフトします。つまり、compareがtrueを返す要素を、compareがfalseを返す要素で上書きします。ただし、ベクトルのサイズは変わりません。

これは、

[最初、最後)の範囲から特定の条件を満たすすべての要素を削除します。最初のバージョンはvalueに等しいすべての要素を削除し、2番目のバージョンは述語pがtrueを返すすべての要素を削除します。

削除は、消去する要素が上書きされるように範囲内の要素をシフトすることによって行われます。範囲の古い端と新しい端の間の要素の値は指定されていません。範囲の新しい終わりへのイテレータが返されます。残っている要素の相対的な順序は保持されます。

したがって、やりたいことは次のように表現する必要があります。

void filterCat (vector<Teacher> &v)
{
   for (vector<Teacher>::iterator it = v.begin(); it != v.end() ; ++it)
   {
      if (!filter_Cat(*i))
      {
           std::cout << i->getName() <<"\t" << i->getCategory() << std::endl;
      }
   }
 }

それはあなたのコードにあるようで、getName()理想的にはそれがすべきではない名前を出力します、代わりにそれは名前を返すべきです。したがって、名前を返すように変更することをお勧めします。そして、同様に同じことをgetCategoryします。名前を正しく選択してください。の場合はgetName()、名前を返すことで名前を取得する必要があります。の場合は、名前を出力printName()する必要があります。


また、あなたが書いたコードは良くありません:

  • グローバル変数は避けてください。
  • if-elseはできるだけ避けてください。より良い方法を学びましょう。
  • 関数オブジェクト(またはファンクター)について学ぶ必要があります
  • constメンバー関数について学ぶ必要があります。
  • iteratorとの違いconst_iterator、およびそれらの使用法を理解する必要があります。
  • const参照とnon-const参照の違いを理解する必要があります。そして、それらを適切に使用してみてください。

だから私はあなたのコードを次のように書くでしょう:

//this is functor, not a function
struct filter_cat
{
   std::string m_cat; //use member data, avoid global variable
   filter_cat(std::string const & cat) : m_cat(cat) {}
   bool operator()(Teacher const & t) const  //const member function
   { 
     return (t.getCat() != m_cat); //getCat should be const member function
   }
};

//pass vector by const reference
void filterCat (vector<Teacher> const & v, filter_cat filter)
{
   //use const_iterator here, instead of iterator 
   for (vector<Teacher>::const_iterator it = v.begin(); it != v.end() ; ++it)
   {
      if (!filter(*i))
      {
           //getName and getCategory should be const member function
           std::cout << i->getName() <<"\t" << i->getCategory() << std::endl;
      }
   }
}

void filterTutorCat(vector<Teacher> const &t)
{
    int choice;
    cout << "No\tCategory" << endl
         << "1\tEnglish" << endl
         << "2\tMath" << endl
         << "3\tScience" << endl
         << "Choose the category you wish to filter :";
    cin >> choice;
    getline(cin, debug);

    //avoid if-else as much as possible, learn better ways!
    std::string cats[] = {"English", "Math", "Science"};

    if(choice <= 3 && choice > 0)
    {
          filterCat(v, filter_cat(cats[choice-1]));
    }
    else
    {
        cout << "Invalid Option" << endl;
    }
}

コメントに記載されているように:getCatgetNameおよびgetCategoryはconstメンバー関数である必要があります。実際、getCategoryカテゴリを返す場合は、getCat必要ありません。

私の問題を解決しました。

于 2012-01-21T06:15:37.057 に答える