C ++ remove_if覆盖我的向量

时间:2012-01-21 05:55:19

标签: c++ vector remove-if

我的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;
    }
 }

2 个答案:

答案 0 :(得分:2)

remove_if从右到左移动比较函数返回false的元素;换句话说,它意味着,它会覆盖比较返回true的元素与元素,compare将返回false。但是,矢量的大小不会改变。

This reads

  

从[first,last]范围中删除满足特定条件的所有元素。第一个版本删除所有等于value的元素,第二个版本删除谓词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会员功能。
  • 您应该了解iteratorconst_iterator之间的区别及其用法。
  • 您应该了解const引用和非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;
    }
}

如评论中所述:getCatgetNamegetCategory应为const成员函数。事实上,如果getCategory返回类别,则甚至不需要getCat

解决了我的问题。

答案 1 :(得分:1)

remove_if收集filter_Cat在容器开头返回false的值。虽然它不会减少容器中元素的数量,但它不会对返回范围之外的元素值做出任何保证。因此,在使用remove_if时,您将丢失值。