c++에서 입 출력 스 트림 교체 기 및 copy 소스 코드 분석

12150 단어 c++stl
c++의 스 트림 교체 기 는 교체 기 중의 특수 한 교체 기 입 니 다.그 중에서 두 가지 교체 기 를 포함 합 니 다.입력 스 트림 교체 기(istreamiterator),출력 스 트림 교체 기(ostreamiterator)。이 두 종류의 교체 기 를 사용 하면 입 출력 흐름 을 용기 로 조작 할 수 있다.헤 더 파일 iterator)
다음은 입 출력 흐름 에서 흔히 볼 수 있 는 간단 한 용법 입 니 다.
#include 
#include 
#include 
#include 

using std::cout;
using std::endl;
using std::cin;
using std::ostream_iterator;
using std::istream_iterator;
using std::vector;
using std::back_insert_iterator;
using std::copy;


int main()
{
  vector vec;//    vector
  copy(istream_iterator(cin),istream_iterator(),back_insert_iterator>(vec));//       int     vector  
  copy(vec.begin(),vec.end(),ostream_iterator(cout," "));// vector          
  return 0;
}


                                //  1

 
 
copy 는 stl 에서 교체 기 를 조작 하 는 알고리즘 입 니 다.세 개의 매개 변 수 는 모두 교체 기 입 니 다.가능 한 실현 방식 은 다음 과 같 습 니 다.
template
OutputIt copy(InputIt first, InputIt last, 
              OutputIt d_first)
{
    while (first != last) {
        *d_first++ = *first++;
    }
    return d_first;
}
                            //  2

코드 2 에서 copy 의 실현 방식 을 보고 코드 1 에서 무엇 을 했 는 지 대충 알 게 되 었 습 니 다.첫 번 째 copy 는 입력 스 트림 교체 기(cin)의 물건 을 vector 에 할당 한 후 교체 기(backinsert_iterator)다음 입력 스 트림 교체 기와 vector 의 후 삽입 교체 기 는 각각+1 에서 설정 한 종료 조건 까지 두 번 째 copy 는 vector 의 데 이 터 를 출력 스 트림 교체 기 에 부여 합 니 다.
난점왜 종료 조건 은 입력 스 트림 교체 기 가 istream 과 같 습 니까?iterator?
2.스 트림 교체 기 입력*backinsert_iterator,일반적인 교체 기 가능 합 니까?
3.copy 에서 교체 기 는 모두+작업 이 있 고 입 출력 스 트림 교체 기 에 도 이+작업 이 있 습 니까?
문제 3.입 출력 스 트림 교체 기 가+연산 자 를 다시 불 러 왔 기 때문에 자신 에 게 돌아 가기 때문에+연산 자 는 괜 찮 습 니 다.
    : ostream_iterator<_tp>& operator++() { return *this; } 
  ostream_iterator<_tp>& operator++(int) { return *this; } 

문제 2 는*d 를 완성 해 야 하기 때 문 입 니 다.first++ = *first++;의 조작,이때 dfirst 는 backinsert_iterator,backinsert_iterator 가 다시 불 러 왔 습 니 다=연산 자 와*연산 자 는 다음 과 같 습 니 다.
 operator=(const typename _Container::value_type& __value) { 
    container->push_back(__value);
    return *this;
  }
  back_insert_iterator<_container>& operator*() { return *this; }

그래서=조작 은 vector.push 에 해당 합 니 다.back(),front 라면insert_iterator 는 vector.push 에 해당 합 니 다.front()。
문제 1 은 istreamiterator 원본 코드 입 니 다:
template ,
          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(); }//      ,       _M_read()  

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

  istream_iterator& operator++() { //    ++     _M_read    
    _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;//    ,    ok _M_ok true
    if (_M_ok) {
      *_M_stream >> _M_value;
      _M_ok = *_M_stream ? true : false;
    }
  }
};

template 
inline bool 
operator==(const istream_iterator<_tp _chart="" _traits="" _dist="">& __x,
           const istream_iterator<_tp _chart="" _traits="" _dist="">& __y) {
  return __x._M_equal(__y);
}

#ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER

template 
inline bool 
operator!=(const istream_iterator<_tp _chart="" _traits="" _dist="">& __x,
           const istream_iterator<_tp _chart="" _traits="" _dist="">& __y) {
  return !__x._M_equal(__y);
}
                        //  3

일단 데이터 멤버.
 istream_type* _M_stream;//흐름  _Tp _M_value;//cin 에서 읽 은 데 이 터 를 임시 저장 합 니 다.  bool _M_ok;//저장 흐름 상태 ok 여부
그 다음 에 구조 함 수 를 보면 삼 구조 함수 가 하나의 흐름 상태 ok 의 대상 을 구성 하고 무 삼 구조 함수 가 하나의 흐름 상태 goodbit 를 1(읽 을 수 없 음)의 대상 으로 구성 하지 않 으 며 삼 구조 함수 구조의 대상 을 무 삼 구조 함수 구조의 대상 으로 중지 조건 으로 하 며 먼저=연산 자 를 봐 야 한다.
return (_M_ok == __x._M_ok) && (!_M_ok || _M_stream == __x._M_stream);
에 해당 하 다,...M_ok == __x._M_ok && !_M_ok )    ||    (_M_ok == __x._M_ok&&_M_stream == __x._M_stream)
번역 다음은 두 개의 스 트림 교체 기 대상M_OK 는 모두 false 또는 둘 다 ok 이 고 이들 이 대응 하 는 흐름 대상 은 같다.
무 참 구조의 교체 기 대상M_stream 은 0 이 고 둘 은 같 을 수 없 기 때문에 둘 만 가능 합 니 다M_OK.다 false 일 때 같 아 요.
대신M_OK 는 false 이 고 흐 르 는 대상 의 goodbit 는 0 이 며 읽 을 수 없 기 때문에 파일 끝 자 를 읽 거나 읽 는 데 실 패 했 습 니 다(fail,예 를 들 어 cin>int.문자열 을 읽 었 습 니 다).
ostream_iterator 출력 스 트림 교체 기 는 입력 스 트림 교체 기와 유사 하 며 다음 과 같 습 니 다.
template  >
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;
};

// The default template argument is declared in iosfwd

// We do not read any characters until operator* is called.  The first
// time operator* is called, it calls getc.  Subsequent calls to getc 
// return a cached character, and calls to operator++ use snextc.  Before
// operator* or operator++ has been called, _M_is_initialized is false.
template
class istreambuf_iterator
  : public iterator
{
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
_CharT istreambuf_iterator<_chart _traits="">::_M_dereference_aux() const
{
  this->_M_getc();
  return _M_c;
}

template
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
void istreambuf_iterator<_chart _traits="">::_M_postincr_aux()
{
  this->_M_getc();
}

template
inline bool operator==(const istreambuf_iterator<_chart _traits="">& __x,
                       const istreambuf_iterator<_chart _traits="">& __y) {
  return __x.equal(__y);
}

#ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER

template
inline bool operator!=(const istreambuf_iterator<_chart _traits="">& __x,
                       const istreambuf_iterator<_chart _traits="">& __y) {
  return !__x.equal(__y);
}

#endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */

// The default template argument is declared in iosfwd
template
class ostreambuf_iterator
  : public iterator
{
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_ostream<_chart _traits="">   ostream_type;

public:
  ostreambuf_iterator(streambuf_type* __buf) : _M_buf(__buf), _M_ok(__buf) {}
  ostreambuf_iterator(ostream_type& __o)
    : _M_buf(__o.rdbuf()), _M_ok(__o.rdbuf() != 0) {}

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

  bool failed() const { return !_M_ok; }

private:
  streambuf_type* _M_buf;
  bool _M_ok;
};

좋은 웹페이지 즐겨찾기