remove_if
смещает элементы, для которых функция сравнения возвращает false, справа налево; другими словами, он перезаписывает элементы, для которых сравнение возвращает true, с элементами, для которых сравнение возвращает false. Однако размер вектора не меняется.
Это читается как ,
Удаляет все элементы, удовлетворяющие определенным критериям, из диапазона [first, last). Первая версия удаляет все элементы, равные значению, вторая версия удаляет все элементы, для которых предикат 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
должны быть постоянными функциями-членами. Фактически, если getCategory
возвращает категорию, то getCat
даже не требуется.
Решил мою проблему.