c++에서 입 출력 스 트림 교체 기 및 copy 소스 코드 분석
12150 단어 c++stl
다음은 입 출력 흐름 에서 흔히 볼 수 있 는 간단 한 용법 입 니 다.
#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;
};