Help | Site Map
Connecting Tech Pros Worldwide
 
 
LinkBack Thread Tools
  #1  
Old December 6th, 2006, 08:13 PM
Paulo Matos
Guest
 
Posts: n/a
Default Using copy for output

Hi all,

Given a list of int, it's rather easy to output them line by line:
std::copy(mylist.begin(), mylist.end(),
std::ostream_iterator<int>(cout, "\n");

Now, there's two ways in which I would like to generalize this:
First, I would like to be able to print a list of pointers to int.
However, I'm guessing this is not possible with copy, right?
I would have to:
for(std::list<int>::const_iterator it = mylist.begin(); it !=
mylist.end() ; ++it) cout << **it << "\n";

Right? Not possible with copy?
Another thing I would like to do it to had a character in-between each
printed int. For example:
If I have a list with 1,2,3,4,5 and I want to print " + " I would get 1
+ 2 + 3 + 4 + 5.
A solution is:
std::string str(" + ");
for(std::list<int>::const_iterator it = mylist.begin(); it !=
mylist.end() ; ++it) {
cout << **it;
std::list<int>::const_iterator aux = it;
if(++aux != mylist.end())
cout << str;
}

Is there any better way? Comments on this? Anyway to do this more
straightforwardly?

Regards,

Paulo Matos

  #2  
Old December 6th, 2006, 08:13 PM
Pete Becker
Guest
 
Posts: n/a
Default Re: Using copy for output

Paulo Matos wrote:
Quote:
If I have a list with 1,2,3,4,5 and I want to print " + " I would get 1
+ 2 + 3 + 4 + 5.
std::copy(mylist.begin(), mylist.end(),
std::ostream_iterator<int>(cout, " + ");

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
  #3  
Old December 6th, 2006, 08:45 PM
Paulo Matos
Guest
 
Posts: n/a
Default Re: Using copy for output


Pete Becker escreveu:
Quote:
Paulo Matos wrote:
Quote:
If I have a list with 1,2,3,4,5 and I want to print " + " I would get 1
+ 2 + 3 + 4 + 5.
>
std::copy(mylist.begin(), mylist.end(),
std::ostream_iterator<int>(cout, " + ");
>
That's what's I did iintially with '\n' however, it's not the same
thing. The result of that is:
1 + 2 + 3 + 4 + 5 +

And I don't want the extra plus in the end. What about if the list
contains pointers to ints?
Quote:
--
>
-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
  #4  
Old December 6th, 2006, 09:15 PM
Roland Pibinger
Guest
 
Posts: n/a
Default Re: Using copy for output

On 6 Dec 2006 13:05:01 -0800, "Paulo Matos" wrote:
Quote:
>Pete Becker escreveu:
Quote:
>Paulo Matos wrote:
Quote:
If I have a list with 1,2,3,4,5 and I want to print " + " I would get 1
+ 2 + 3 + 4 + 5.
>>
>std::copy(mylist.begin(), mylist.end(),
>std::ostream_iterator<int>(cout, " + ");
>
>That's what's I did iintially with '\n' however, it's not the same
>thing. The result of that is:
>1 + 2 + 3 + 4 + 5 +
>
>And I don't want the extra plus in the end.
add:

cout << "\b\b\b"; // works for some ostreams
Quote:
>What about if the list contains pointers to ints?
I'd use a for loop anyway. copy is 'semantically' wrong for output.

Best wishes,
Roland Pibinger

  #5  
Old December 6th, 2006, 10:35 PM
Salt_Peter
Guest
 
Posts: n/a
Default Re: Using copy for output


Paulo Matos wrote:
Quote:
Hi all,
>
Given a list of int, it's rather easy to output them line by line:
std::copy(mylist.begin(), mylist.end(),
std::ostream_iterator<int>(cout, "\n");
>
Now, there's two ways in which I would like to generalize this:
First, I would like to be able to print a list of pointers to int.
However, I'm guessing this is not possible with copy, right?
I would have to:
for(std::list<int>::const_iterator it = mylist.begin(); it !=
mylist.end() ; ++it) cout << **it << "\n";
>
Right? Not possible with copy?
Another thing I would like to do it to had a character in-between each
printed int. For example:
If I have a list with 1,2,3,4,5 and I want to print " + " I would get 1
+ 2 + 3 + 4 + 5.
A solution is:
std::string str(" + ");
for(std::list<int>::const_iterator it = mylist.begin(); it !=
mylist.end() ; ++it) {
cout << **it;
std::list<int>::const_iterator aux = it;
if(++aux != mylist.end())
cout << str;
}
>
Is there any better way? Comments on this? Anyway to do this more
straightforwardly?
>
Regards,
>
Paulo Matos
With an operator<< overload...

#include <iostream>
#include <ostream>
#include <list>
#include <algorithm>
#include <iterator>

template< typename T >
class NSequence
{
T t;
public:
NSequence(const T& r_t) : t(r_t) { }
T operator() () { return t++; }
};

template< typename T >
std::ostream&
operator<<(std::ostream& os, std::list< T >& r_l)
{
std::copy( r_l.begin(),
--r_l.end(),
std::ostream_iterator< int >(os, " + "));
return os << *(--r_l.end());
}

int main()
{
std::list< int nlist;
// insert integers from 1 to 6
std::generate_n( std::back_inserter(nlist),
6,
NSequence< int >(1) );
// print ints with " + "
std::cout << nlist << std::endl;
}

/*
1 + 2 + 3 + 4 + 5 + 6
*/

If you need the same with a std::list< int* >,
i'ld suggest wrapping it in a templated class with a std::list member.

  #6  
Old December 7th, 2006, 12:55 PM
Pete Becker
Guest
 
Posts: n/a
Default Re: Using copy for output

Paulo Matos wrote:
Quote:
Pete Becker escreveu:
>
Quote:
>Paulo Matos wrote:
Quote:
>>If I have a list with 1,2,3,4,5 and I want to print " + " I would get 1
>>+ 2 + 3 + 4 + 5.
>std::copy(mylist.begin(), mylist.end(),
>std::ostream_iterator<int>(cout, " + ");
>>
>
That's what's I did iintially with '\n' however, it's not the same
thing. The result of that is:
1 + 2 + 3 + 4 + 5 +
>
Whoops, sorry. As long as you've got a bidirectional iterator, you can
do this:

mylist::iterator end = mylist.end();
if (mylist.begin() != end)
{
--end;
std::copy(mylist.begin(), end,
std::ostream_iterator<int>(cout, " + "));
std::copy(--mylist.end(), end,
std::ostream_iterator<int>(cout, ""));
}

Alternatively, you can write an algorithm that takes an output stream
rather than an iterator:

template <class InIt>
void show(InIt first, ostream& str, const char *sep)
{
if (first != last)
str << *first++;
while (first != last)
str << sep << *first++;
}

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
  #7  
Old December 7th, 2006, 01:05 PM
Pete Becker
Guest
 
Posts: n/a
Default Re: Using copy for output

Salt_Peter wrote:
Quote:
return os << *(--r_l.end());
A note of caution here: this works if operator-- is a member of the
iterator type returned by end(), but doesn't work if it's a free
function. The problem is that -- modifies its argument. The call to
end() creates a temporary object, and you can't pass that to a
non-member function that takes its argument by reference.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
  #8  
Old December 7th, 2006, 01:55 PM
Salt_Peter
Guest
 
Posts: n/a
Default Re: Using copy for output


Pete Becker wrote:
Quote:
Salt_Peter wrote:
Quote:
return os << *(--r_l.end());
>
A note of caution here: this works if operator-- is a member of the
iterator type returned by end(), but doesn't work if it's a free
function. The problem is that -- modifies its argument. The call to
end() creates a temporary object, and you can't pass that to a
non-member function that takes its argument by reference.
>
Its a std::list so thats a bidirectional iterator with --iter and
iter-- member-operators available.
If the iterator involved was only a forward iterator, that would indeed
fail.

The warning about the temporary is relevant and for the record, i don't
like the above statement at all even if the reference to std::list<>
had been made const.

Thanks for your input.

  #9  
Old December 7th, 2006, 02:15 PM
Pete Becker
Guest
 
Posts: n/a
Default Re: Using copy for output

Salt_Peter wrote:
Quote:
Pete Becker wrote:
Quote:
>Salt_Peter wrote:
Quote:
>> return os << *(--r_l.end());
>A note of caution here: this works if operator-- is a member of the
>iterator type returned by end(), but doesn't work if it's a free
>function. The problem is that -- modifies its argument. The call to
>end() creates a temporary object, and you can't pass that to a
>non-member function that takes its argument by reference.
>>
>
Its a std::list so thats a bidirectional iterator with --iter and
iter-- member-operators available.
It's a std::list, so it provides a bidirectional iterator. The
requirement for bidirectional iterators is that the expressions --iter
and iter-- are both valid and have specified semantics. They are not
required to be implemented with member functions. If pre-increment is a
free function, --r_l.end() is ill-formed.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
  #10  
Old December 7th, 2006, 03:35 PM
Paulo Matos
Guest
 
Posts: n/a
Default Re: Using copy for output



Thanks a lot for all your input. :) Great, I just learned some more C++
today!

 

Bookmarks

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are Off
[IMG] code is Off
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On

What is Bytes?

We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights. Get the best answers to your questions from over network members.
Post your question now . . .
It's fast and it's free

Popular Articles