Deleting every second element from List

Hello!

I'm trying to delete every second element from a linked list.
My current code, kinda does the job but it crashes at the end.
It shows the 5's only and then crash.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
        list<int> ListOfInts;
	list<int>::iterator ListIt;

	ListOfInts.push_back(5);
	ListOfInts.push_back(2);
	ListOfInts.push_back(5);
	ListOfInts.push_back(2);
	ListOfInts.push_back(5);
	ListOfInts.push_back(2);
	ListOfInts.push_back(5);
	ListOfInts.push_back(2);
	ListOfInts.push_back(5);
	ListOfInts.push_back(2);
	ListOfInts.push_back(5);
	ListOfInts.push_back(2);
	ListOfInts.push_back(5);
	ListOfInts.push_back(2);


	for (ListIt = ListOfInts.begin(); ListIt != ListOfInts.end(); ListIt++) {
		if ((*ListIt) % 2 == 0) {

			ListIt = ListOfInts.erase(ListIt);
		}
		cout << *ListIt << " " << endl;
	}


I understand that.. when you delete a certian node, it would brake the chain in this case.
But im not sure how to fix this.
I believe i could possibly use 2 iterators. And make Iterator 1 the beginning and increment the second one and once i get to the second to copy it to Iterator 1 and then delete Iterator 1 etc.. but i was wondering is it possible to fix my current code and make it work in some way ?
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <list>

int main()
{
    std::list<int> lst { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 , 10, 11, 12, 13, 14, 15, 16 } ;

    auto it = lst.begin() ;
    while( it != lst.end() && ++it != lst.end() ) it = lst.erase(it) ;

    for( int v : lst ) std::cout << v << ' ' ;
    std::cout << '\n' ;
}

http://coliru.stacked-crooked.com/a/aa4de0cd8b344e95
Oh god..

That is way more elegant and simplified than i though it will be.

Thank you very much ahaha.

EDIt: Just to ask.. would it be the same idea if doing it for every third or fourth element ?
Last edited on
> would it be the same idea if doing it for every third or fourth element ?

Yes. Writing a helper function may be convenient.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <list>

// advance the iterator by skipping over n elements or getting to the end
// return true if end was not reached
template < typename ITERATOR > bool skip( ITERATOR& iter, std::size_t n, ITERATOR end )
{
    while( n-- && iter != end ) ++iter ;
    return iter != end ;
}

int main()
{
    std::list<int> lst { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 } ;

    auto it = lst.begin() ; // erase every 4th element (skip 3 elements after each erase)
    while( skip( it, 3, lst.end() ) ) it = lst.erase(it) ;

    for( int v : lst ) std::cout << v << ' ' ;
    std::cout << '\n' ;
}

http://coliru.stacked-crooked.com/a/237fe51841fbf0b9
Could also just copy desired elements over to a second container.
One unfortunate aspect of iterators is that you have to check each increment against end() or you could be running past the container's end.

It would be nice to incorporate something like std::next(it, 3) to skip over three places without an end() check, but then you'd need a counter separately to compare a running total against the container size. (For lists since C++11, at least size() is constant).
Topic archived. No new replies allowed.