STL列表,删除所有奇数

STL list, delete all the odd numbers

本文关键字:删除 列表 STL      更新时间:2023-10-16

我正在尝试学习如何与STL一起工作,并尝试编写一个将收到reffference to to列表的函数,并将尝试删除所有奇数成员。我的代码有一个小问题。这里是我的代码

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-没有发生,因为我开始时。

最简单的方法是使用 std::list::remove_if。这将根据一元谓词从列表中删除元素。例如,

myvector.remove_if([](int n) { return n % 2 != 0; });

使用" stl" *的最佳方法是知道其中的内容。

对于Pre-C 11实现(例如实际的STL),您可以传递一个函数:

bool is_odd(int n) { return n % 2 != 0; }
myvector.remove_if(is_odd);

*" stl"表示STL,但这也适用C 标准库

方法擦除返回迭代器后返回到下一个元素。因此,执行此类任务的通常方法是以下

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类具有removeremove_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 

好吧,我找到了一种方法,那就是将p 从循环声明中移动到其中。

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++;
    }
} 

现在我很好奇我是否可以这样做,并且仍然保持完整的循环。

由于您正在学习,最好忘记'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());
}

就您的代码而言,您只需使用自动请不要在循环容器上删除元素是有风险的。矢量通常很好,但是当您开始使用其他数据结构时,事情变得更加讨厌。