通用的输入输出---------cout的扩展

本文介绍了如何扩展C++的cout来方便地输出一维和二维容器,包括使用`ostream_iterator`遇到的问题及解决方案。通过重载`<<`运算符和理解C++的命名空间规则,实现了通用的容器输出功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

                            Cout的扩展      

        写这个笔记完全是由一道题起的,题目就是如何用iostream迭代器实现类及容器的输出(想必大家早已厌烦了写一个while或for循环来做这件事吧,而且这样做函数基本都是专用,不能实现通用)。(结合C++Primer 第11章)

        最初尝试代码如下:


#include<iostream>

#include<fstream>

#include<vector>

#include<algorithm>

#include<iterator>

#include<string>

using namespace std;

template<class T,classbaseType>

void Show(T &v,baseType r)

{

     //第二个参数仅仅是为了传递类型

     ostream_iterator<baseType>out(cout," ");

      copy(v.begin(),v.end(),out);

     cout<<endl;

}

template<class T>

void Show(T &v)

{

      Show(v,v[0]);               //注意重载函数时,常量引用和非常量引用是不同函数

}

int main()

{
     vector<string> vec(10,"Bosch");

     Show(vec,string(""));

     Show(vec);

     return 0;
}

1)        ostream_iterator<baseType> out(cout," ")是声明一个ostream迭代器,其声明将baseType类型的对象写到输出流cout(此处为标准输出,也可以是其它输出流)ostream_iterator对象,在写入过程中,使用delim作为元素的分隔。Delim是以空字符结束字符数组。

2)        copy(v.begin(),v.end(),out),则是将类型T中的在迭代器对范围内的元素拷贝到out所迭代的输出流中。

3)        这个函数实现了输出任何一维容器的功能(当然容器中必须存储基础类型)

 

      输出一维成功后,我尝试了一下二维容器,结果不甚理想,会在编译期报出类似找不到匹配的“<<“操作符的错误,先看程序:


#include<iostream>

#include<fstream>

#include<vector>

#include<algorithm>

#include<iterator>

#include<string>

using  namespace std;


template<class T,class baseType>

void Show(T &v,baseType r)

{
      ostream_iterator<baseType> out(cout," ");

      copy(v.begin(),v.end(),out);

      cout<<endl;

}

 
template<class T>

void Show(T &v)

{

       Show(v,v[0]);

}

 
int main()

{

       vector<string> vec(10,"Bosch");

       Show(vec,string(""));

       Show(vec);

      
       vector<vector<string> > dvec(2,vec);

       Show(dvec[0],string(""));

       Show(*dvec.begin(),string(""));

      
       Show(dvec,vec);

       ostream_iterator< vector<string> > out(cout," ");

       copy(dvec.begin(),dvec.end(),out);

 

}

Show(dvec,vec);

copy(dvec.begin(),dvec.end(),out);

上面两句话编译不通过,而且出来很大篇幅错误,真是无语,我是看不懂了。后经有经验的程序员高人指点,说是“<<“无法找到匹配的,我开始有了概念,大概是没有输出vector<string>类型的操作符重载,那么很自然的想到重载cout。说做就做,见下面程序。

 


#include<iostream>

#include<fstream>

#include<vector>

#include<algorithm>

#include<iterator>

#include<string>

using  namespace std;

ostream& operator << (ostream& os,vector<string>&vec)

{

       vector<string>::iterator iter = vec.begin();

       while (iter != vec.end())

       {

             os<<*iter++<<" 0 ";

       }

      os<<endl;

 

      return os;

}
 
template<class T,class baseType>

void Show(T &v,baseType r)

{

        ostream_iterator<baseType> out(cout," ");

        copy(v.begin(),v.end(),out);

        cout<<endl;

}

 
template<class T>

void Show(T &v)

{

       Show(v,v[0]);

}


int main()

{

       vector<string> vec(10,"Bosch");

       Show(vec,string(""));

       Show(vec);

       cout<<vec;

       vector<vector<string> > dvec(2,vec);

       Show(dvec[0],string(""));

       Show(*dvec.begin(),string(""));

       ostream_iterator< vector<string> > out(cout," ");              


       copy(dvec.begin(),dvec.end(),out);

       Show(dvec,vec);
}

       copy(dvec.begin(),dvec.end(),out);

       Show(dvec,vec);

这两行仍然编译不通过,提示错误相同,还是找不到匹配的“<<“操作符,这样我着实郁闷。现在只能是copy内部有问题了,在stackoverflow网站找到了代码:


template<class InputIterator, class OutputIterator>

OutputIterator mycopy (InputIterator first, InputIterator last, OutputIterator result)

{

      while (first != last) *result++ = *first++;

      return result;

}

 

       看完有点小惊讶,copy函数居然这么简单,看来我们真的不要把标准库看的太难啊,可是就这么简单的一行代码,怎么会,我只能猜测vector<string>不支持赋值操作,结果简单的测试一下马上推翻了这个假设。

        这下这是黔驴技穷了,没办法硬着头皮找一下ostream_iterator的实现,同时命名为myostream_iterator(不重命名会重定义)


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

class myostream_iterator :public iterator<output_iterator_tag, void, void, void, void>

{

  basic_ostream<charT,traits>* out_stream;

  const charT* delim;

 

public:

  typedef charT char_type;

  typedef traits traits_type;

  typedef basic_ostream<charT,traits> ostream_type;

 

  myostream_iterator(ostream_type& s) : out_stream(&s), delim(0) {}

  myostream_iterator(ostream_type& s, const charT* delimiter)

    : out_stream(&s), delim(delimiter) { }

  myostream_iterator(const myostream_iterator<T,charT,traits>& x)

    : out_stream(x.out_stream), delim(x.delim) {}

  ~myostream_iterator() {}

 

  //关键函数,也是“<<“找不到匹配的地方。

  myostream_iterator<T,charT,traits>& operator= (const T& value) {

    *out_stream << value;

    if (delim!=0) *out_stream << delim;

    return *this;

  }

 

 

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

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

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

};

 

        耐心研究一下,这个类并不复杂,除了一个较为底层的basic_ostream<charT,traits>类型没怎么见过外,其他的都很容易理解。而且不难发现错误就处在函数:myostream_iterator<T,charT,traits>& operator= (constT& value)中的 *out_stream << value;这句话,所以重载还是必要的,那么为什么重载了不好使呢,我又尝试了重载的另一个版本:


typedef basic_ostream<char,char_traits<char> >  ostream_Type;

///you can see the ostream_Type as ostream.

 

ostream_Type& operator << (ostream_Type& os,vector<string>& vec)

 {

            vector<string>::iterator iter = vec.begin();

            while (iter != vec.end())

            {

                        os<<(*iter++)<<" ";

            }

            os<<endl;

            return os;

 }

开始把这个函数放在类里面结果不好使,提示函数调用少一个参数(至于怎么改进目前还不知道)后来把这个函数放在外面,结果仍然出错。结果发现:

 myostream_iterator<T,charT,traits>&operator= (const T& value)

 

的第二个参数是常量类型,所以我们重载函数也必须是const类型的引用参数,否则不会匹配,也就不会调用。

 

注意:在C++中,重载函数时,编译器会识别常引用参数非常引用参数,所以会产生不同的函数版本,忽略这个特性会产生很隐蔽的错误。因为非常引用的形参是不会接受常量引用作为实参的。

 

上述事实也是重载后仍然无效的错觉,改进后我们仍然发现编译不通过,这是因为:

vector<string>::iterator iter = vec.begin();

这条语句的原因,我们必须给它声明常量迭代器。修改后的代码如下:


typedef basic_ostream<char,char_traits<char> >  ostream_Type;

///you can see the ostream_Type as ostream.

 

ostream_Type& operator << (ostream_Type& os,const vector<string>& vec)

  {

        vector<string>::const_iterator iter = vec.begin();

        while (iter != vec.end())

        {

             os<<(*iter++)<<" ";

        }

        os<<endl;

        return os;

  }

 

至此我们需要的二维容器也可以正常输出了,最终代码如下:


#include<iostream>

#include<fstream>

#include<vector>

#include<algorithm>

#include<iterator>

#include<string>

using  namespace std;

typedef basic_ostream<char,char_traits<char> >  ostream_Type;

///you can see the ostream_Type as ostream.

 

ostream_Type& operator << (ostream_Type& os,const vector<string>& vec)

{

     vector<string>::const_iterator iter = vec.begin();

     while (iter != vec.end())

     {

          os<<(*iter++)<<" ";

     }

     os<<endl;

     return os;

}
 

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

class myostream_iterator :public iterator<output_iterator_tag, void, void, void, void>

{

  basic_ostream<charT,traits>* out_stream;

  //ostream* out_stream;

  const charT* delim;

public:

  typedef charT char_type;

  typedef traits traits_type;

  typedef basic_ostream<charT,traits> ostream_type;

  //typedef ostream ostream_type;

  myostream_iterator(ostream_type& s) : out_stream(&s), delim(0) {}

  myostream_iterator(ostream_type& s, const charT* delimiter)

    : out_stream(&s), delim(delimiter) { }

  myostream_iterator(const myostream_iterator<T,charT,traits>& x)

    : out_stream(x.out_stream), delim(x.delim) {}

  ~myostream_iterator() {}

 

  myostream_iterator<T,charT,traits>& operator= (const T& value) {

    *out_stream << value;

    if (delim!=0) *out_stream << delim;

    return *this;

  }

 

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

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

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

};

 
template<class T,class baseType>

void Show(T &v,baseType r)

{

     myostream_iterator<baseType> out(cout," ");

     copy(v.begin(),v.end(),out);

     cout<<endl;

}


/*ostream& operator << (ostream& os,const vector<string>&vec)

{

   vector<string>::const_iterator iter = vec.begin();

     while (iter != vec.end())

     {

          os<<*iter++<<" 0 ";

     }

     os<<endl;

     return os;

}*/

 
template<class InputIterator, class OutputIterator>

OutputIterator mycopy (InputIterator first, InputIterator last, OutputIterator result)

{

   while (first != last) *result++ = *first++;

   return result;

}

 
template<class T>

void Show(T &v)

{
     Show(v,v[0]);
}

int main()

{

     vector<string> vec(10,"Bosch");

     Show(vec);

     Show(vec,string(""));

     cout<<vec;

     vector<vector<string> > dvec(2,vec);

     Show(dvec[0],string(""));

     Show(*dvec.begin(),string(""));

     myostream_iterator< vector<string> > out(cout," ");

     vector<string> tes = vec;

     //*out<<*dvec.begin();

     mycopy(dvec.begin(),dvec.end(),out);


     cout<<"*******************Success*********************"<<endl;

     Show(dvec,vec);
}

 

ostream& operator << (ostream& os,const vector<string>&vec)

ostream_Type& operator << (ostream_Type& os,constvector<string>& vec)

两个版本在这个程序中都可以用。加重的部分几乎等价,至于差别以后在探究吧。

 

       上面使用的是我们自己的代码下面除了重载cout完全用库函数:即使用库中的ostream_iterator仍然报错,无语,几经尝试我仍旧束手无策,那么没办法,看linux下标准库源码吧,毕竟网上找的ostream_iterator源代码也许不够权威。

        度娘真是个好东西,经过一番搜索得知iostream_iterator包含在头文件<iterator>中,然后进入/usr/include/c++下找到该头文件,打开之后如下所示:


 

从中无法得到直接定义,但是我们稍加观察会发现有个stream_iterator.h那么我们可以猜测,在该文件中,打开文件果真是有的(此处只贴出ostream_iterator代码,其他完整代码见博客源码目录下):


/**

   *  @brief  Provides output iterator semantics for streams.

   *

   *  This class provides an iterator to write to an ostream.  The type Tp is

   *  the only type written by this iterator and there must be an

   *  operator<<(Tp) defined.

   *

   *  @param  Tp  The type to write to the ostream.

   *  @param  CharT  The ostream char_type.

   *  @param  Traits  The ostream char_traits.

  */

  template<typename _Tp, typename _CharT = char,

           typename _Traits = char_traits<_CharT> >

    class ostream_iterator

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

    {

    public:

      //@{

      /// Public typedef

      typedef _CharT                         char_type;

      typedef _Traits                        traits_type;

      typedef basic_ostream<_CharT, _Traits> ostream_type;

      //@}

 

    private:

      ostream_type*   _M_stream;

      const _CharT*   _M_string;

 

    public:

      /// Construct from an ostream.

      ostream_iterator(ostream_type& __s) : _M_stream(&__s), _M_string(0) {}

 

      /**

       *  Construct from an ostream.

       *

       *  The delimiter string @a c is written to the stream after every Tp

       *  written to the stream.  The delimiter is not copied, and thus must

       *  not be destroyed while this iterator is in use.

       *

       *  @param  s  Underlying ostream to write to.

       *  @param  c  CharT delimiter string to insert.

      */

      ostream_iterator(ostream_type& __s, const _CharT* __c)

      : _M_stream(&__s), _M_string(__c)  { }

 

      /// Copy constructor.

      ostream_iterator(const ostream_iterator& __obj)

      : _M_stream(__obj._M_stream), _M_string(__obj._M_string)  { }

 

      /// Writes @a value to underlying ostream using operator<<.  If

      /// constructed with delimiter string, writes delimiter to ostream.

      ostream_iterator&

      operator=(const _Tp& __value)

      {

    __glibcxx_requires_cond(_M_stream != 0,

                 _M_message(__gnu_debug::__msg_output_ostream)

                 ._M_iterator(*this));

    *_M_stream << __value;

    if (_M_string) *_M_stream << _M_string;

    return *this;

      }

 
      ostream_iterator&

      operator*()

      { return *this; }

 
      ostream_iterator&

      operator++()

      { return *this; }

 
      ostream_iterator&

      operator++(int)

      { return *this; }

    };

 

        看完源码,就更加使我们困惑了,为什么会这样,这个版本和我们上面的版本几乎相同,于是我想到将标准ostream_iterator替换上面的myostream_iterator(当然此时不需要包含<iterator>),结果出乎意料,结果一切正常。仔细捉摸一下发现可能是标准库无法找到我重载的函数,随即,我便想到把上面的库文件stream_iterator复制一份命名为iostream_iterator.h放到当前工作目录中,然后用include<iostream_iterator.h>包含,果不出所料,这样就会报错,然后我将重载的"<<"函数放入该头文件中,编译通过。至此我们算是找到了问题的根源。


最终源码:

(1)iostream_iterator.h


// Stream iterators

// Copyright (C) 2001, 2004, 2005, 2009 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.

// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
// <http://www.gnu.org/licenses/>.

/** @file stream_iterator.h
 *  This is an internal header file, included by other library headers.
 *  You should not attempt to use it directly.
 */

#ifndef _STREAM_ITERATOR_H
#define _STREAM_ITERATOR_H 1

#pragma GCC system_header

#include <debug/debug.h>

_GLIBCXX_BEGIN_NAMESPACE(std)

  /// Provides input iterator semantics for streams.
  template<typename _Tp, typename _CharT = char,
           typename _Traits = char_traits<_CharT>, typename _Dist = ptrdiff_t>
    class istream_iterator
    : public iterator<input_iterator_tag, _Tp, _Dist, const _Tp*, const _Tp&>
    {
    public:
      typedef _CharT                         char_type;
      typedef _Traits                        traits_type;
      typedef basic_istream<_CharT, _Traits> istream_type;

    private:
      istream_type*    _M_stream;
      _Tp        _M_value;
      bool        _M_ok;

    public:
      ///  Construct end of input stream iterator.
      istream_iterator()
      : _M_stream(0), _M_value(), _M_ok(false) {}

      ///  Construct start of input stream iterator.
      istream_iterator(istream_type& __s)
      : _M_stream(&__s)
      { _M_read(); }

      istream_iterator(const istream_iterator& __obj)
      : _M_stream(__obj._M_stream), _M_value(__obj._M_value),
        _M_ok(__obj._M_ok)
      { }

      const _Tp&
      operator*() const
      {
    __glibcxx_requires_cond(_M_ok,
                _M_message(__gnu_debug::__msg_deref_istream)
                ._M_iterator(*this));
    return _M_value;
      }

      const _Tp*
      operator->() const { return &(operator*()); }

      istream_iterator&
      operator++()
      {
    __glibcxx_requires_cond(_M_ok,
                _M_message(__gnu_debug::__msg_inc_istream)
                ._M_iterator(*this));
    _M_read();
    return *this;
      }

      istream_iterator
      operator++(int)
      {
    __glibcxx_requires_cond(_M_ok,
                _M_message(__gnu_debug::__msg_inc_istream)
                ._M_iterator(*this));
    istream_iterator __tmp = *this;
    _M_read();
    return __tmp;
      }

      bool
      _M_equal(const istream_iterator& __x) const
      { return (_M_ok == __x._M_ok) && (!_M_ok || _M_stream == __x._M_stream); }

    private:
      void
      _M_read()
      {
    _M_ok = (_M_stream && *_M_stream) ? true : false;
    if (_M_ok)
      {
        *_M_stream >> _M_value;
        _M_ok = *_M_stream ? true : false;
      }
      }
    };

  ///  Return true if x and y are both end or not end, or x and y are the same.
  template<typename _Tp, typename _CharT, typename _Traits, typename _Dist>
    inline bool
    operator==(const istream_iterator<_Tp, _CharT, _Traits, _Dist>& __x,
           const istream_iterator<_Tp, _CharT, _Traits, _Dist>& __y)
    { return __x._M_equal(__y); }

  ///  Return false if x and y are both end or not end, or x and y are the same.
  template <class _Tp, class _CharT, class _Traits, class _Dist>
    inline bool
    operator!=(const istream_iterator<_Tp, _CharT, _Traits, _Dist>& __x,
           const istream_iterator<_Tp, _CharT, _Traits, _Dist>& __y)
    { return !__x._M_equal(__y); }

  /**
   *  @brief  Provides output iterator semantics for streams.
   *
   *  This class provides an iterator to write to an ostream.  The type Tp is
   *  the only type written by this iterator and there must be an
   *  operator<<(Tp) defined.
   *
   *  @param  Tp  The type to write to the ostream.
   *  @param  CharT  The ostream char_type.
   *  @param  Traits  The ostream char_traits.
  */
  template<typename _Tp, typename _CharT = char,
           typename _Traits = char_traits<_CharT> >
    class ostream_iterator
    : public iterator<output_iterator_tag, void, void, void, void>
    {
    public:
      //@{
      /// Public typedef
      typedef _CharT                         char_type;
      typedef _Traits                        traits_type;
      typedef basic_ostream<_CharT, _Traits> ostream_type;
      //@}

    private:
      ostream_type*    _M_stream;
      const _CharT*    _M_string;

    public:
      /// Construct from an ostream.
      ostream_iterator(ostream_type& __s) : _M_stream(&__s), _M_string(0) {}

      /**
       *  Construct from an ostream.
       *
       *  The delimiter string @a c is written to the stream after every Tp
       *  written to the stream.  The delimiter is not copied, and thus must
       *  not be destroyed while this iterator is in use.
       *
       *  @param  s  Underlying ostream to write to.
       *  @param  c  CharT delimiter string to insert.
      */
      ostream_iterator(ostream_type& __s, const _CharT* __c)
      : _M_stream(&__s), _M_string(__c)  { }

      /// Copy constructor.
      ostream_iterator(const ostream_iterator& __obj)
      : _M_stream(__obj._M_stream), _M_string(__obj._M_string)  { }

      /// Writes @a value to underlying ostream using operator<<.  If
      /// constructed with delimiter string, writes delimiter to ostream.
      ostream_iterator&
      operator=(const _Tp& __value)
      {
    __glibcxx_requires_cond(_M_stream != 0,
                _M_message(__gnu_debug::__msg_output_ostream)
                ._M_iterator(*this));
    *_M_stream << __value;
    if (_M_string) *_M_stream << _M_string;
    return *this;
      }

      ostream_iterator&
      operator*()
      { return *this; }

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

      ostream_iterator&
      operator++(int)
      { return *this; }
    };
    
    
typedef basic_ostream<char,char_traits<char> >  ostream_Type;    
ostream_Type& operator << (ostream_Type& os,const vector<string>& vec)
{
    vector<string>::const_iterator iter = vec.begin();
    while (iter != vec.end())
    {
        os<<(*iter++)<<" ";
    }
    os<<endl;
    return os;
}
 
ostream_Type& operator << (ostream_Type& os,vector<string>& vec)
{
    vector<string>::iterator iter = vec.begin();
    while (iter != vec.end())
    {
        os<<(*iter++)<<" ";
    }
    os<<endl;
    return os;
}

_GLIBCXX_END_NAMESPACE

#endif

 (1)main.c


#include<iostream>
#include<fstream>
#include<vector>
#include<algorithm>
#include<string>
#include"iostream_iterator.h"
using  namespace std;
//typedef basic_ostream<char,char_traits<char> >  ostream_Type;
///you can see the ostream_Type as ostream.


template<class T,class baseType>
void Show(T &v,baseType r)
{
	ostream_iterator<baseType> out(cout," ");
	copy(v.begin(),v.end(),out);
	cout<<endl;
}


/*ostream& operator << (ostream& os,const vector<string>&vec)
{
   vector<string>::const_iterator iter = vec.begin();
	while (iter != vec.end())
	{
		os<<*iter++<<" 0 ";
	}
	os<<endl;
	return os;
}*/

template<class InputIterator, class OutputIterator>
OutputIterator mycopy (InputIterator first, InputIterator last, OutputIterator result)
{
   while (first != last) *result++ = *first++;
   return result;
}

template<class T>
void Show(T &v)
{
	Show(v,v[0]);
}


int main()
{
	vector<string> vec(10,"Bosch");
	Show(vec);
	Show(vec,string(""));
	cout<<vec;
	vector<vector<string> > dvec(2,vec);
	Show(dvec[0],string(""));
	Show(*dvec.begin(),string(""));
	ostream_iterator< vector<string> > out(cout," ");
	vector<string> tes = vec;
	//*out<<*dvec.begin();
	copy(dvec.begin(),dvec.end(),out);
	
	cout<<"*******************Success*********************"<<endl;
	Show(dvec,vec);
}



      尽管解决了这个问题,又引出了一个值得思考的问题,当把代码直接贴入main.c 时,是可以找到重载的"<<"的,为什么include不可以呢,以前我们不是可以把include的动作理解为"抄写"吗?

           通过耐心测试发现,根源不在于我们对include的理解错误,而在于,命名空间的问题,iostream_iterator.h 所使用的命名空间和我们主文件不同,所以找不到函数。在iostream_iterator.h前面加一条using namespace std;问题圆满解决;



          看来命名空间是个值得探讨的东西,我们需要好好研究一下。


 优快云高人指点:

这是是c++名字查找规则引起的。要想找到自定义的operator<<(xxx, vector<xxx>)函数,有以下几种办法:
① 将该函数的定义放在namespace std中(一般名字查找规则);
② 像版主那样,在与该函数相同的命名空间内定义自己的ostream_iterator。(将标准库的相应版本拷贝出来改个类名即可)(一般名字查找规则)
③ 提供vector<xxx>的一个隐式类型转换类vector_wrapper,并未该类提供operator<<(xxx, vector_wrapper)(Koenig名字查找)


所以目前一个较为理想的解决方案是,将重载的"<<"放入std中,如

namespace std{

ostream& operator << (ostream& os,const vector<string>&vec)
{
   vector<string>::const_iterator iter = vec.begin();
	while (iter != vec.end())
	{
		os<<*iter++<<" 0 ";
	}
	os<<endl;
	return os;
}

}

 参考:

http://bytes.com/topic/c/answers/716006-ostream_iterator-vector-pair-int-string
http://www.cnblogs.com/zhenjing/archive/2010/10/20/1856309.html

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值