我正在尝试学习如何使用STL并尝试编写一个函数来接收对列表的引用并尝试删除所有奇数成员。 我的代码中有一点问题。这是我的代码
void removeOdds(list<int>& myvector)
{
for(list<int>::iterator p=myvector.begin(); p !=myvector.end();p++)
{
if(*p%2 !=0)
{
list<int>::iterator temp=myvector.erase(p);
p=temp;
if(p !=myvector.begin())
p--;
}
}
}
我遇到的问题是,如果我传递一个包含1 3 5 2 6 7的列表。删除1后,它显然会跳到5,而不会看到3。 我怎么能解决这个问题,因为p ++会增加,而p--不会因为我在开头而发生。
答案 0 :(得分:4)
最简单的方法是使用std::list::remove_if
。这将根据一元谓词从列表中删除元素。例如,
myvector.remove_if([](int n) { return n % 2 != 0; });
使用&#34; STL&#34; * 的最佳方式是了解其中的内容。
对于预C ++ 11实现(例如实际的STL),您可以传递一个函数:
bool is_odd(int n) { return n % 2 != 0; }
myvector.remove_if(is_odd);
*&#34; STL&#34;表示STL,但这也适用于C ++标准库
答案 1 :(得分:2)
方法擦除将迭代器返回到删除后的下一个元素。因此,执行此类任务的常用方法如下
void removeOdds( std::list<int> &myvector )
{
for ( auto it = myvector.begin(); it != myvector.end(); )
{
if ( *it % 2 !=0 )
{
it = myvector.erase( it );
}
else
{
++it;
}
}
}
至于你的代码,循环语句总是增加迭代器
for(list<int>::iterator p=myvector.begin(); p !=myvector.end();p++)
^^^^
考虑到课程std::list
的方法remove
和remove_if
会删除满足给定条件的所有元素。
这是一个展示两种方法的示范程序
#include <iostream>
#include <list>
void removeOdds( std::list<int> &myvector )
{
for ( auto it = myvector.begin(); it != myvector.end(); )
{
if ( *it % 2 !=0 )
{
it = myvector.erase( it );
}
else
{
++it;
}
}
}
int main()
{
std::list<int> l = { 1, 3, 5, 2, 6, 7 };
for ( auto x : l ) std::cout << x << ' ';
std::cout << std::endl;
removeOdds( l );
for ( auto x : l ) std::cout << x << ' ';
std::cout << std::endl;
l = { 1, 3, 5, 2, 6, 7 };
for ( auto x : l ) std::cout << x << ' ';
std::cout << std::endl;
l.remove_if( []( int x ) { return x % 2; } );
for ( auto x : l ) std::cout << x << ' ';
std::cout << std::endl;
}
程序输出
1 3 5 2 6 7
2 6
1 3 5 2 6 7
2 6
答案 2 :(得分:0)
好的,我发现了一种方法,就是将p ++从for循环声明转移到其中,就像这样。
void removeOdds(list<int>& myvector)
{
for(list<int>::iterator p=myvector.begin(); p !=myvector.end();)
{
if(*p%2 !=0)
{
list<int>::iterator temp=myvector.erase(p);
p=temp;
}
else
p++;
}
}
现在我很好奇,如果我能做到这一点,仍然保持我的for循环完整。
答案 3 :(得分:0)
既然你正在学习,你最好忘记'C'的做事方式并直接跳到C ++ 11。
这是现代C ++中的代码
void removeOdds(vector<int>& myvector)
{
auto new_end = std::remove_if (myvector.begin(), myvector.end(),
[](const auto& value){ return value%2 !=0 }
);
myvector.erase(new_end, myvector.end());
}
就您的代码而言,只需使用auto即可提高可读性 请注意,在容器上循环时删除元素是有风险的。你通常对一个向量很好,但是当你开始使用其他数据结构时,事情变得更加讨厌。