stl_iterator.h 二

来源:互联网 发布:mac系统怎么编辑pdf 编辑:程序博客网 时间:2024/04/30 08:38

六. istream_iterator

istream_iterator的目的是从输入流中读取数据, 迭代器类型:input_iterator_tag. 接收一个输入流为参数, istream_iterator保存这个输入流,并且每次operator++的时候从输入流中读取一个数据, operator*取到所读取数据的值, operator->是取得所读取数据的引用。  从源码来看,一个输入流传入一个迭代器,没有问题, 但是如果一个输入流传入几个迭代器, 并且每个迭代器都执行++, 那么可能输入流的数据就会遭到严重破坏。 所以,使用istream_iterator要小心。 当*_M_stream 为false, 则说明输入流结束, 可能收到了'/0/字符. 实现:

template <class _Tp,
          class _CharT = char, class _Traits = char_traits<_CharT>,
          class _Dist = ptrdiff_t>
class istream_iterator {
public:
  typedef _CharT                         char_type;
  typedef _Traits                        traits_type;
  typedef basic_istream<_CharT, _Traits> istream_type;

  typedef input_iterator_tag             iterator_category;
  typedef _Tp                            value_type;
  typedef _Dist                          difference_type;
  typedef const _Tp*                     pointer;
  typedef const _Tp&                     reference;

  istream_iterator() : _M_stream(0), _M_ok(false) {}
  istream_iterator(istream_type& __s) : _M_stream(&__s) { _M_read(); }

  reference operator*() const { return _M_value; }
  pointer operator->() const { return &(operator*()); }

  istream_iterator& operator++() {
    _M_read();
    return *this;
  }
  istream_iterator operator++(int)  {
    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:
  istream_type* _M_stream;
  _Tp _M_value;
  bool _M_ok;

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

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);
}

七. ostream_iterator

用途应当是格式化输入, 迭代器类型output_iterator_tag.  接收一个输出流作为参数,  输出迭代器只需要实现operator=, 其他的几个操作符都啥也不干,直接返回, 实现:

template <class _Tp,
          class _CharT = char, class _Traits = char_traits<_CharT> >
class ostream_iterator {
public:
  typedef _CharT                         char_type;
  typedef _Traits                        traits_type;
  typedef basic_ostream<_CharT, _Traits> ostream_type;

  typedef output_iterator_tag            iterator_category;
  typedef void                           value_type;
  typedef void                           difference_type;
  typedef void                           pointer;
  typedef void                           reference;

  ostream_iterator(ostream_type& __s) : _M_stream(&__s), _M_string(0) {}
  ostream_iterator(ostream_type& __s, const _CharT* __c)
    : _M_stream(&__s), _M_string(__c)  {}
  ostream_iterator<_Tp>& operator=(const _Tp& __value) {
    *_M_stream << __value;
    if (_M_string) *_M_stream << _M_string;
    return *this;
  }
  ostream_iterator<_Tp>& operator*() { return *this; }
  ostream_iterator<_Tp>& operator++() { return *this; }
  ostream_iterator<_Tp>& operator++(int) { return *this; }
private:
  ostream_type* _M_stream;
  const _CharT* _M_string;
};

注意operator=, 当_M_string不为0, 那么每次向输出迭代器赋值, 输出迭代器都会首先向输出流写值,然后写_M_string这个格式串, 而达到格式化的目的。

八. istreambuf_iterator

istreambuf_iterator的目的是从basic_streambuf流中读取数据, 迭代器类型:input_iterator_tag.

 接收一个basic_streambuf流或basic_istream为参数, basic_istream可通过rdbuf()转为basic_streambuf. 

此外还存储  streambuf_type* _M_buf;  mutable _CharT _M_c;  mutable bool _M_eof : 1;  mutable bool _M_is_initialized : 1; 这4个成员.

 _M_buf是流的引用,  _M_c是当前读出来的值,  _M_eof标记流是否结束,  _M_is_initialized标记是否开始. 

除了从中读取的流是basic_streambuf外,其他和istream_iterator比较相似。 实现的区别主要在于读取, 这里相对复杂一些。_M_getc是读取字符,  _M_nextc是下一个字符。  注意M_equal_aux, _M_dereference_aux。 分别是两个辅助函数, 用来判等和第一次解引用时调用。 实现:

template<class _CharT, class _Traits>
class istreambuf_iterator
  : public iterator<input_iterator_tag, _CharT,
                    typename _Traits::off_type, _CharT*, _CharT&>
{
public:
  typedef _CharT                           char_type;
  typedef _Traits                          traits_type;
  typedef typename _Traits::int_type       int_type;
  typedef basic_streambuf<_CharT, _Traits> streambuf_type;
  typedef basic_istream<_CharT, _Traits>   istream_type;

public:
  istreambuf_iterator(streambuf_type* __p = 0) { this->_M_init(__p); }
  istreambuf_iterator(istream_type& __is) { this->_M_init(__is.rdbuf()); }

  char_type operator*() const
    { return _M_is_initialized ? _M_c : _M_dereference_aux(); }

  istreambuf_iterator& operator++() { this->_M_nextc(); return *this; }
  istreambuf_iterator  operator++(int) {
    if (!_M_is_initialized)
      _M_postincr_aux();
    istreambuf_iterator __tmp = *this;
    this->_M_nextc();
    return __tmp;
  }

  bool equal(const istreambuf_iterator& __i) const {
    return this->_M_is_initialized && __i._M_is_initialized
      ? this->_M_eof == __i._M_eof
      : this->_M_equal_aux(__i);
  }

private:
  void _M_init(streambuf_type* __p) {
    _M_buf = __p;
    _M_eof = !__p;
    _M_is_initialized = _M_eof;
  }

  char_type _M_dereference_aux() const;
  bool _M_equal_aux(const istreambuf_iterator&) const;
  void _M_postincr_aux();

  void _M_nextc() {
    int_type __c = _M_buf->snextc();
    _M_c = traits_type::to_char_type(__c);   
    _M_eof = traits_type::eq_int_type(__c, traits_type::eof());
    _M_is_initialized = true;
  }

  void _M_getc() const {
    int_type __c = _M_buf->sgetc();
    _M_c = traits_type::to_char_type(__c);
    _M_eof = traits_type::eq_int_type(__c, traits_type::eof());
    _M_is_initialized = true;
  }

private:
  streambuf_type* _M_buf;
  mutable _CharT _M_c;
  mutable bool _M_eof : 1;
  mutable bool _M_is_initialized : 1;
};

template<class _CharT, class _Traits>
_CharT istreambuf_iterator<_CharT, _Traits>::_M_dereference_aux() const
{
  this->_M_getc();
  return _M_c;
}

template<class _CharT, class _Traits>
bool istreambuf_iterator<_CharT, _Traits>
  ::_M_equal_aux(const istreambuf_iterator& __i) const
{
  if (!this->_M_is_initialized)
    this->_M_getc();
  if (!__i._M_is_initialized)
    __i._M_getc();

  return this->_M_eof == __i._M_eof;
}

template<class _CharT, class _Traits>
void istreambuf_iterator<_CharT, _Traits>::_M_postincr_aux()
{
  this->_M_getc();
}

template<class _CharT, class _Traits>
inline bool operator==(const istreambuf_iterator<_CharT, _Traits>& __x,
                       const istreambuf_iterator<_CharT, _Traits>& __y) {
  return __x.equal(__y);
}

九. ostreambuf_iterator

ostreambuf_iterator和ostream_iterator很类似, 只是接受的参数和输出的对象不同, 这里输出的对象是basic_streambuf. 最重要的函数, 唯一的操作符重载:

  ostreambuf_iterator& operator=(char_type __c) {
    _M_ok = _M_ok && !traits_type::eq_int_type(_M_buf->sputc(__c),
                                               traits_type::eof());
    return *this;
  }   

原创粉丝点击