Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

ostream_iterator and the delimiter before the item

92 views
Skip to first unread message

ShaunJ

unread,
Jun 15, 2009, 3:40:26 PM6/15/09
to
I often need to output a list with a delimiter (such as a tab or a
comma) before the item rather than after (which is where the end-of-
line will go). ostream_iterator puts the delimiter after the item. Is
there a simple solution for creating an ostream_iterator that puts the
delimiter before the item?

If I do it in a for loop, it's easy, of course. But the function I'm
calling takes an output iterator parameter, and to use a for loop I
would have to store all the results in a list first, which would take
a bunch of memory and is totally unnecessary.

Thanks,
Shaun

Alf P. Steinbach

unread,
Jun 15, 2009, 5:09:28 PM6/15/09
to
* ShaunJ:

class TabbedIntIter
{
private:
std::ostream* pMyStream;
public:
typedef char char_type;
typedef std::ostream ostream_type;
typedef std::ostream::traits_type traits_type;

TabbedIntIter( std::ostream& stream )
: pMyStream( &stream )
{}

TabbedIntIter& operator*() { return *this; }
TabbedIntIter& operator++() { return *this; }

TabbedIntIter& operator=( int x )
{
(*pMyStream) << '\t' << x;
return *this;
}
};

int main()
{
foo( TabbedIntIter( std::cout ) );
}


Cheers & hth.,

- Alf

--
Due to hosting requirements I need visits to <url: http://alfps.izfree.com/>.
No ads, and there is some C++ stuff! :-) Just going there is good. Linking
to it is even better! Thanks in advance!

Jerry Coffin

unread,
Jun 15, 2009, 5:10:50 PM6/15/09
to
In article <f2d6c584-c903-4eb3-a35d-a9de5fd98728
@d2g2000pra.googlegroups.com>, sjac...@gmail.com says...

> I often need to output a list with a delimiter (such as a tab or a
> comma) before the item rather than after (which is where the end-of-
> line will go). ostream_iterator puts the delimiter after the item. Is
> there a simple solution for creating an ostream_iterator that puts the
> delimiter before the item?

Fairly simple to implement, if somewhat more verbose than anybody would
like:

// Warning: only minimally tested.
// prefix_iterator.h
#include <ostream>
#include <iterator>

template <class T,
class charT=char,
class traits=std::char_traits<charT>
>
class prefix_ostream_iterator :
public std::iterator<std::output_iterator_tag,void,void,void,void>
{
charT const* delimiter;
std::basic_ostream<charT,traits> *os;
public:
typedef charT char_type;
typedef traits traits_type;
typedef std::basic_ostream<charT,traits> ostream_type;

prefix_ostream_iterator(ostream_type& s)
: os(&s),delimiter(0)
{}
prefix_ostream_iterator(ostream_type& s, charT const *d)
: os(&s),delimiter(d)
{}
prefix_ostream_iterator<T,charT,traits>& operator=(T const &item)
{
// Here's the only real change from ostream_iterator:
// Normally, the '*os << item;' would come before the 'if'.
if (delimiter != 0)
*os << delimiter;
*os << item;
return *this;
}

prefix_ostream_iterator<T,charT,traits> &operator*() {
return *this;
}
prefix_ostream_iterator<T,charT,traits> &operator++() {
return *this;
}
prefix_ostream_iterator<T,charT,traits> &operator++(int) {
return *this;
}
};

// Minimal test file:
#include <vector>
#include <iostream>
#include "prefix_iterator.h"

int main() {
std::vector<int> x;

x.push_back(1);
x.push_back(3);
x.push_back(5);

std::copy(x.begin(), x.end(),
prefix_ostream_iterator<int>(std::cout, "|"));
return 0;
}

The test code is pretty minimal, but more probably isn't necessary --
this is little more than a trivial modification of the code as it's
presented in the standard, and most of it is pretty basic boilerplate.

--
Later,
Jerry.

The universe is a figment of its own imagination.

ShaunJ

unread,
Jun 15, 2009, 7:09:32 PM6/15/09
to
Thanks, Jerry. Worked like a charm.

Cheers,
Shaun

red floyd

unread,
Jun 15, 2009, 7:13:57 PM6/15/09
to
Jerry,

I took the liberty of modifying your prefix_output_iterator to create
the much
desired "infix iterator", would generate:

1|3|5

from your test case.

// Warning: only minimally tested.

// infix_iterator.h
// Lifted from Jerry Coffin's 's prefix_ostream_iterator
#if !defined(INFIX_ITERATOR_H_)
#define INFIX_ITERATOR_H_
#include <ostream>
#include <iterator>

template <class T,
class charT=char,
class traits=std::char_traits<charT> >

class infix_ostream_iterator :


public std::iterator<std::output_iterator_tag,void,void,void,void>
{

std::basic_ostream<charT,traits> *os;
charT const* delimiter;
bool first_elem;


public:
typedef charT char_type;
typedef traits traits_type;
typedef std::basic_ostream<charT,traits> ostream_type;

infix_ostream_iterator(ostream_type& s)
: os(&s),delimiter(0), first_elem(true)
{}
infix_ostream_iterator(ostream_type& s, charT const *d)
: os(&s),delimiter(d), first_elem(true)
{}
infix_ostream_iterator<T,charT,traits>& operator=(T const &item)


{
// Here's the only real change from ostream_iterator:
// Normally, the '*os << item;' would come before the 'if'.

if (!first_elem && delimiter != 0)
*os << delimiter;
*os << item;
first_elem = false;
return *this;
}

infix_ostream_iterator<T,charT,traits> &operator*() {
return *this;
}
infix_ostream_iterator<T,charT,traits> &operator++() {
return *this;
}
infix_ostream_iterator<T,charT,traits> &operator++(int) {
return *this;
}

};
#endif


Jerry Coffin

unread,
Jun 15, 2009, 7:46:00 PM6/15/09
to
In article <68e82c55-86bd-4d68-ab38-
747bd8...@c19g2000prh.googlegroups.com>, redf...@gmail.com says...

> Jerry,
>
> I took the liberty of modifying your prefix_output_iterator to create
> the much desired "infix iterator", would generate:
>
> 1|3|5
>
> from your test case.

Good call. I'm not quite sure why a suffix was chosen for the standard
-- I think it's probably desired the least often of the three obvious
possibilities.

Thomas J. Gritzan

unread,
Jun 15, 2009, 7:52:35 PM6/15/09
to
Jerry Coffin schrieb:

> In article <68e82c55-86bd-4d68-ab38-
> 747bd8...@c19g2000prh.googlegroups.com>, redf...@gmail.com says...
>> Jerry,
>>
>> I took the liberty of modifying your prefix_output_iterator to create
>> the much desired "infix iterator", would generate:
>>
>> 1|3|5
>>
>> from your test case.
>
> Good call. I'm not quite sure why a suffix was chosen for the standard
> -- I think it's probably desired the least often of the three obvious
> possibilities.

Because it works great when you simply want a newline after each item.

--
Thomas

James Kanze

unread,
Jun 16, 2009, 3:42:38 AM6/16/09
to
On Jun 16, 1:46 am, Jerry Coffin <jcof...@taeus.com> wrote:
> In article <68e82c55-86bd-4d68-ab38-
> 747bd811c...@c19g2000prh.googlegroups.com>, redfl...@gmail.com says...

> > I took the liberty of modifying your prefix_output_iterator
> > to create the much desired "infix iterator", would generate:

> > 1|3|5

> > from your test case.

> Good call. I'm not quite sure why a suffix was chosen for the
> standard -- I think it's probably desired the least often of
> the three obvious possibilities.

I've never needed the prefix, and of the latter two, infix is
actually tricky if the iterators are getting copied. (In
practice, however, using a copy of an output iterator once
anything has been written through it is probably going to cause
problems anyway, so Red Floyd's solution should work. But I
think I'd still have used a shared_ptr to a dynamically
allocated bool for "first_element".)

--
James Kanze (GABI Software) email:james...@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

0 new messages