STL列表,删除所有奇数

时间:2015-05-13 09:01:31

标签: c++ stl

我正在尝试学习如何使用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--不会因为我在开头而发生。

4 个答案:

答案 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的方法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 

答案 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即可提高可读性 请注意,在容器上循环时删除元素是有风险的。你通常对一个向量很好,但是当你开始使用其他数据结构时,事情变得更加讨厌。