开发者

How to change delimiter's position?

This example :

#include <iostream>
#include <iterator>
#include <algorithm>

int main()
{
    int v[] = { 1, 2, 3 };

    std::copy( &v[0], &v[3], std::ostream_iterator< int >( std::cout, "\n " ) );
}

produces next output :

1
 2
 3
 

Is there a way to change the example to make it produce next output?


 1
 2
 3

PS I 开发者_如何学Cknow I could use the for loop, but I am interested in a solution that uses algorithms and iterators.


There is no way to do this with std::ostream_iterator. (IMHO, there should be, but it's not there.) If you don't mind writing an extra small function or class, you can use std::transform, e.g.:

struct FormatString
{
    std::string operator()( std::string const& original ) const
    {
        return ' ' + original + '\n';
    }
};

//  ...
std::transform(
    v.begin(), v.end(),
    std::ostream_iterator<std::string>( std::cout ), 
    FormatString() );

If you have C++11, you can use a lambda for the FormatString.

I find the need for this occurs often enough that I've written a PatsubstTransformer—a functional object which basically implements the $(patsubst...) function of GNU make. So I would just have to write:

std::transform(
    v.begin(), v.end(),
    std::ostream_iterator<std::string>( std::cout ),
    PatsubstTransformer( "%", " %\n" ) );

I find I use this a lot. (I also find using std::transform more appropriate than std::copy, since what I'm outputting is a transformation.)


If you want to use C++11 you can use a lambda.

e.g like this:

int v[] = { 1, 2, 3};

std::for_each( &v[0], &v[3], [](int i){ std::cout << " " << i << "\n";} );


Use std::cout << " ", instead of std::cout as:

std::copy(v, v+3, std::ostream_iterator<int>(std::cout << " ", "\n " ) );

Here the expression std::cout << " " first evaluates which prints a single space to the output, and the evaluated value which is std::ostream& gets passed to std::ostream_iterator

Now the output will be aligned correctly:

 1
 2
 3

Working code : http://www.ideone.com/kSdpk

By the way, don't write &v[3]. That invokes Undefined bevahior. Write v+3.


Output a single space before the std::copy.


No, not really. ostream_iterator isn't configurable like that.

So you'll have to use the pre-space "workaround" as found in other answers, and manually chop off that final line.


BTW It's been noted that &v[3], strictly speaking, invokes undefined behaviour due to the implicit dereference in the sub-expression v[3]. Prefer &v[0]+3 (or just v+3) — "having" a pointer to one-past-the-end of an array is okay, as long as it's not dereferenced.


You could make your own kind of ostream_iterator that does this, as the following example demonstrates.

Yes, it's verbose; however, you can also change it around however you like to suit your changing needs:

#include <iostream>
#include <iterator>
#include <algorithm>
 
template <class T, class charT = char, class traits = std::char_traits<charT> >
struct ostream_iterator_x
  : std::iterator<std::output_iterator_tag, void, void, void, void> {
    
    typedef charT char_type;
    typedef traits traits_type;
    typedef std::basic_ostream<charT,traits> ostream_type;
    
    ostream_iterator_x(ostream_type& s, const charT* pre = 0, const charT* post = 0)
       :    s(s)
       ,  pre(pre)
       , post(post) {};
    
    ostream_iterator_x(const ostream_iterator_x& x)
       :    s(x.s)
       ,  pre(x.pre)
       , post(x.post) {};
    
    ~ostream_iterator_x() {}
    
    ostream_iterator_x& operator=(const T& value) {
       if (pre  != 0) s << pre;
       s << value;
       if (post != 0) s << post;
       
       return *this;
    }
    
    ostream_iterator_x& operator*()     { return *this; }
    ostream_iterator_x& operator++()    { return *this; }
    ostream_iterator_x& operator++(int) { return *this; }
    
  private:
    ostream_type& s;
    const charT* pre;
    const charT* post;
};
 
int main()
{
    int v[] = { 1, 2, 3 };
    std::copy(v, v+3, ostream_iterator_x<int>(std::cout, " ", "\n"));
}

// Output:
//  1
//  2
//  3

(I used [n3290: 24.6/2] to determine the members and base-specification required for this to work and to be standard-compliant.)

Live demo.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜