http://blog.daum.net/coolprogramming/93
4, 삽입 반복자
삽입 반복자(insert iterator)는 알고리즘에서 반복자가 가리키는 위치에 값을 "덮어"(overwrite)쓰지 않고 "삽입"(insert)할 수 있도록 바꿔주는 반복자입니다.
STL은 3 가지의 삽입 반복자를 제공합니다.
back_insert_iterator : push_back 멤버 함수를 사용하여 삽입
- 시퀀스 컨테이너(string, vector, list, deque)는 push_back 멤버 함수를 제공하므로 사용 가능
front_insert_iterator : push_front 멤버 함수를 사용하여 삽입
- list와 deque만 push_front 멤버 함수를 제공하므로 사용 가능
insert_iterator : insert 멤버 함수를 사용하여 삽입
- 모든 컨테이너는 insert 멤버 함수를 제공하므로 사용 가능
반복자를 이용한 덮어쓰기와 삽입을 그림으로 보입니다.
1) 덮어쓰기 모드
2) 삽입 모드
일반적으로 알고리즘은 덥어쓰기로 동작하므로 알고리즘을 사용하기 전에 저장할 원소의 size가 존재해야 합니다.
간단한 copy 알고리즘을 예로 사용합니다.
#include <iostream>
#include <algorithm>#include <vector>
using namespace std;
void main( )
{
vector<int> v1;
vector<int> v2(3);
v1.push_back(10);
v1.push_back(20);
v1.push_back(30);
copy(v1.begin(), v1.end(), v2.begin());
for( int i = 0 ; i < v2.size() ; i++)
cout << v2[i] << " ";
cout << endl;
}
- 10 20 30
v1.begin()~v2.end()까지의 원소를 모두 v2에 저장합니다. 이때 v2는 저장할 개수만큼의 size를 가지고 있어야합니다. 여기서는 3개입니다.
만약 size를 가지고 있지 않다면 실행 오류가 발생합니다.
v2의 size는 0 입니다.
#include <iostream>
#include <algorithm>#include <vector>
using namespace std;
void main( )
{
vector<int> v1;
vector<int> v2;
v1.push_back(10);
v1.push_back(20);
v1.push_back(30);
copy(v1.begin(), v1.end(), v2.begin());
for( int i = 0 ; i < v2.size() ; i++)
cout << v2[i] << " ";
cout << endl;
}
- 안녕~~!
v2의 size가 0이므로 copy 알고리즘에서 실행 오류가 발생합니다.
이것은 해결하려면 copy 알고리즘에 삽입 반복자를 전달하면 됩니다.
insert_iterator를 사용한 예제입니다.
#include <iostream>
#include <algorithm>#include <vector>
using namespace std;
void main( )
{
vector<int> v1;
vector<int> v2;
v1.push_back(10);
v1.push_back(20);
v1.push_back(30);
copy(v1.begin(), v1.end(), inserter< vector<int> >(v2, v2.begin()) );
for( int i = 0 ; i < v2.size() ; i++)
cout << v2[i] << " ";
cout << endl;
}
- 10 20 30
inserter는 insert_iterator를 생성합니다. 이 삽입 반복자는 insert() 멤버 함수를 사용하여 삽입니다.
inserter는 템플릿 함수로 insert_iterator를 반환합니다. 첫 번째 인자에 컨테이너를 두 번째 인자에 삽입할 위치의 반복자를 지정하면 됩니다.
또 다른 예제입니다.
#include <iostream>
#include <algorithm>#include <vector>
using namespace std;
void main( )
{
vector<int> v1;
vector<int> v2;
v1.push_back(10);
v1.push_back(20);
v1.push_back(30);
v2.push_back(100);
v2.push_back(200);
v2.push_back(300);
copy(v1.begin(), v1.end(), inserter< vector<int> >(v2, v2.begin() ) );
for( int i = 0 ; i < v2.size() ; i++)
cout << v2[i] << " ";
cout << endl;
}
- 10 20 30 100 200 300
v2가 3개의 원소(100,200,300)를 가지고 있고 v2.begin()에 삽입 위치를 지정했으므로 앞쪽에 삽입됩니다.
back_insert_iterator를 사용한 예제입니다.
#include <iostream>
#include <algorithm>#include <vector>
using namespace std;
void main( )
{
vector<int> v1;
vector<int> v2;
v1.push_back(10);
v1.push_back(20);
v1.push_back(30);
v2.push_back(100);
v2.push_back(200);
v2.push_back(300);
copy(v1.begin(), v1.end(), back_inserter< vector<int> >(v2) );
for( int i = 0 ; i < v2.size() ; i++)
cout << v2[i] << " ";
cout << endl;
}
- 100 200 300 10 20 30
back_inserter는 back_insert_iterator를 생성합니다. 이 삽입 반복자는 push_back() 멤버 함수를 사용하여 삽입(추가)합니다.
back_inserter는 템플릿 함수로 back_insert_iterator를 반환합니다. 함수의 인자에 컨테이너 지정하면 됩니다.
vector는 push_front 멤버 함수가 없으므로 front_insert_iterator는 사용할 수 없습니다.
#include <iostream>
#include <algorithm>#include <vector>
using namespace std;
void main( )
{
vector<int> v1;
vector<int> v2;
v1.push_back(10);
v1.push_back(20);
v1.push_back(30);
v2.push_back(100);
v2.push_back(200);
v2.push_back(300);
copy(v1.begin(), v1.end(), front_inserter< vector<int> >(v2) );
for( int i = 0 ; i < v2.size() ; i++)
cout << v2[i] << " ";
cout << endl;
}
안녕~~!
에러입니다. front_inserter는 템플릿 함수로 front_insert_iterator를 반환하지만 vector는 push_front() 멤버 함수가 없으므로 front_insert_iterator를 사용할 수 없습니다.
list는 push_front 멤버 함수를 가지고 있으므로 front_insert_iterator를 사용할 수 있습니다.
#include <iostream>#include <algorithm>
#include <list>
using namespace std;
void main( )
{
list<int> lt1;
list<int> lt2;
lt1.push_back(10);
lt1.push_back(20);
lt1.push_back(30);
lt2.push_back(100);
lt2.push_back(200);
lt2.push_back(300);
copy(lt1.begin(), lt1.end(), front_inserter< list<int> >(lt2) );
list<int>::iterator iter;
for( iter = lt2.begin(); iter != lt2.end() ; iter++)
cout << *iter << " ";
cout << endl;
}
- 30 20 10 100 200 300
push_front 멤버 함수를 사용하여 정수를 삽입합니다.
5, 입,출력 스트림 반복자
입,출력 스트림 반복자(input,output stream iterator)는 I/O 스트림에 연결된 조금 특별한 반복자입니다. 알고리즘에서 스트림 입출력을 쉽게 수행할 수 있도록 제공합니다. 입력 스트림 반복자는 istream_iterator 클래스를 출력 스트림 반복자는 ostream_iterator 클래스를 사용합니다.
copy 알고리즘에서 출력 스트림 반복자를 사용한 예제입니다.
#include <iostream>#include <algorithm>
#include <vector>
using namespace std;
void main( )
{
vector<int> v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(40);
v.push_back(50);
copy(v.begin(), v.end(), ostream_iterator< int >(cout, " " ) );
cout<< endl;
copy(v.begin(), v.end(), ostream_iterator< int >(cout, ", " ) );
cout<< endl;}
- 10 20 30 40 50
10, 20, 30, 40, 50,
ostream_iterator는 템플릿 클래스로 출력 반복자를 추상화한 클래스입니다. 템플릿 인자는 출력 타입이며(int) 생성자의 첫 번째 인자는 출력 스트림 객체, 두 번째 인자는 출력 값들 사이에 출력될 문자열입니다.
다음은 istream_iterator의 간단한 예제입니다.
#include <algorithm>
#include <vector>
using namespace std;
void main( )
{
vector<int> v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(40);
v.push_back(50);
copy( istream_iterator<int>(cin), istream_iterator<int>(), ostream_iterator< int >(cout, "," ) );
cout<< endl;
}
- 10 20 30 40 50^Z
10,20,30,40,50,
예제는 입력 스트림 객체(cin)에서 입력되는 정수들을 스트림 끝까지 입력 받아 출력하는 예제입니다.
istream_iterator<int>( cin )은 cin(입력 스트림 객체)을 통해 입력되는 정수 값을 입력 받는 반복자를 istream_iterator<int>( )은 입력 스트림 반복자의 끝 표시기(end marker)를 역할을 하는 입력 반복자를 의미합니다.
여기까지 C++, STL QS1을 모두 마무리합니다. ㅠ.ㅠ...
10개월 동안 해오던 일을 마무리하니 시원함? 아쉬움? 뿌듯함? 허탈함?이 모두 공존합니다.
아직 못 다한 고급(?)적인 내용은 C++, STL QS2에서 공부합니다. QS2는 조금 어려운 내용이 될 수도...
수고하셨습니다. 꾸벅!
'STLTemplate > STL & EffectiveSTL' 카테고리의 다른 글
반복자 어댑터(Iterator Adaptors) – inserter(), back_inserter(), front_inserter() (0) | 2012.11.01 |
---|---|
iterator_traits( 반복자 특질 )이란 무엇인가? (0) | 2012.11.01 |
오토포인터 auto_ptr (0) | 2012.11.01 |
STL 연관컨테이너 bitset 예제소스 (0) | 2012.11.01 |
typename 을 써야 하는 순간 & iterator_traits (0) | 2012.11.01 |