我的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;
}
}
答案 0 :(得分:2)
remove_if
从右到左移动比较函数返回false的元素;换句话说,它意味着,它会覆盖比较返回true的元素与元素,compare将返回false。但是,矢量的大小不会改变。
从[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()
,那么它应该打印名称。
另外,你写的代码不好:
const
会员功能。iterator
和const_iterator
之间的区别及其用法。所以我会把你的代码写成:
//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;
}
}
如评论中所述:getCat
,getName
和getCategory
应为const成员函数。事实上,如果getCategory
返回类别,则甚至不需要getCat
。
解决了我的问题。
答案 1 :(得分:1)
remove_if收集filter_Cat在容器开头返回false的值。虽然它不会减少容器中元素的数量,但它不会对返回范围之外的元素值做出任何保证。因此,在使用remove_if时,您将丢失值。