I am trying to learn how to work with STL and tried to write a function which will recieve a refference to a list and will try to delete all odd members. I am having a sligh
Method erase returns iterator to the next element after deleted. So the usual approach to such a task is the following
void removeOdds( std::list<int> &myvector )
{
for ( auto it = myvector.begin(); it != myvector.end(); )
{
if ( *it % 2 !=0 )
{
it = myvector.erase( it );
}
else
{
++it;
}
}
}
As for your code then the loop statement always increases the iterator
for(list<int>::iterator p=myvector.begin(); p !=myvector.end();p++)
^^^^
Take into account that class std::list
has methods remove
and remove_if
that erase all elements that satisfy the given criteria.
Here is a demonstrative program that shows the both approaches
#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;
}
The program output is
1 3 5 2 6 7
2 6
1 3 5 2 6 7
2 6
Since you're learning, you better forget the 'C' way of doing things and jump directly into C++11.
Here's your code in modern 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());
}
As far as your code goes, you can improve readability a lot just by using auto Please not that it is risky to remove elements while looping on a container. You're usually fine with a vector, but when you start using other data structures things get more nasty.
Ok, I found one way to do this, and that was to move p++ from for loop declaration into inside it, like this.
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++;
}
}
Now I am curious if I can do this and still keep my for loop intact.
The easiest way to do it would be to use std::list::remove_if. This removes elements from the list based on a unary predicate. For example,
myvector.remove_if([](int n) { return n % 2 != 0; });
The best way to work with the "STL"* is to know what is in it.
For pre-C++11 implementations (such as the actual STL), you can pass a function:
bool is_odd(int n) { return n % 2 != 0; }
myvector.remove_if(is_odd);
*"STL" means the STL but this also applies the C++ standard library