Re: copying elements from a <list> to <deque>
James Kanze wrote:
On Sep 25, 11:24 am, Kai-Uwe Bux <jkherci...@gmx.net> wrote:
Erik Wikstr?m wrote:
On 2007-09-25 09:59, arnuld wrote:
It works fine. any advice on making it better or if I can
improve my C++ coding skills:
/* C++ Primer - 4/e
*
* Chapter 9 - Sequential Containers
* exercise 9.18 - STATEMENT
* Write a program to copy elements from a list of
"ints" * to 2 "deques". The list elements that are even should go
into one deque * and even elements should go into 2nd deque.
*
*/
#include <iostream>
#include <list>
#include <deque>
#include <algorithm>
#include <iterator>
int main()
{
std::cout << "enter some integers: ";
std::list<int> ilist;
/* copy elements from std::cin into ilist */
std::copy( (std::istream_iterator<int>( std::cin )),
(std::istream_iterator<int>()),
std::back_inserter( ilist ) );
std::deque<int> deque_of_evens;
std::deque<int> deque_of_odds;
/* copy even elements into 1 deque and odds into the other */
for( std::list<int>::const_iterator iter = ilist.begin();
iter != ilist.end();
++iter)
{
if( *iter % 2 == 0 )
{
deque_of_evens.push_back( *iter );
}
else
{
deque_of_odds.push_back( *iter );
}
You might replace the if with:
(*iter % 2 == 0 ? deque_of_evens :
deque_of_odds).push_back( *iter ) ;
Opinions about this vary; I tend not to use ?: very much for
lvalues, but in this case, it does draw attention to the fact
that *all* of the elements end up in one of the two deques.
}
std::cout << "\n Printing Deque of Even Integers: ";
std::copy( deque_of_evens.begin(),
deque_of_evens.end(),
std::ostream_iterator<int>( std::cout, " " ) );
std::cout << "\n\n Printing Deque of Odd Integers: ";
std::copy( deque_of_odds.begin(),
deque_of_odds.end(),
std::ostream_iterator<int>( std::cout, " " ) );
std::cout << std::endl;
return 0;
}
You should research the (IMO badly named) remove_copy_if
algorithm and create a predicate to determine if the element
is even or not.
And: you should implement the missing (sic!) copy_if algorithm
and use the same predicate for the other copy job.
I'm not sure that I agree with either of these recommendations.
Both smack of obfuscation, and forcing things just to use a
standard (or non-standard, in the case of copy_if) algorithm.
I have a great deal of sympathy for that sentiment. Functors tend to move
code from the place where you would like to see it to some other place.
That is generally not so good.
For a more experienced programmer, I might consider a
boost::filter_iterator, e.g.:
std::deque< int > evens(
boost::make_filter_iterator< IsEven >( ilist.begin(),
ilist.end() ),
boost::make_filter_iterator< IsEven >( ilist.end(),
ilist.end() ) ) ;
std::deque< int > odds(
boost::make_filter_iterator< IsOdd >( ilist.begin(),
ilist.end() ),
boost::make_filter_iterator< IsOdd >( ilist.end(),
ilist.end() ) ) ;
This allows correct initialization; it would even allow making
evens and odds const. But it still requires moving the test out
of the loop, and even out of the function.
[snip]
In a case like this, I like lambda:
std::remove_copy_if( ilist.begin(), ilist.end(),
std::back_inserter( deque_of_evens ),
_1 % 2 != 0 );
std::remove_copy_if( ilist.begin(), ilist.end(),
std::back_inserter( deque_of_odds ),
_1 % 2 == 0 );
(yet, I would prefer copy_if :-)
I agree, though, that cases where lambda is this concise are rare. But
compared to using std::binder..., std::modulus, ... lambda is great.
Best
Kai-Uwe Bux