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) 덮어쓰기 모드

insert_iterator(1).png

2) 삽입 모드

insert_iterator2.png

일반적으로 알고리즘은 덥어쓰기로 동작하므로 알고리즘을 사용하기 전에 저장할 원소의 size가 존재해야 합니다.

간단한 copy 알고리즘을 예로 사용합니다.

#include <iostream>

#include <algorithm>
#include <vector>
using namespace std;

void main( )
{
vector<int> v1;
vector<intv2(3);


v1.push_back(10);

v1.push_back(20);
v1.push_back(30);

copy(v1.begin(), v1.end(), v2.begin());

forint i = 0 ; i < v2.size() ; i++)
cout << v2[i] << " ";
cout << endl;
}

  1. 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<intv2;


v1.push_back(10);

v1.push_back(20);
v1.push_back(30);

copy(v1.begin(), v1.end(), v2.begin());

forint i = 0 ; i < v2.size() ; i++)
cout << v2[i] << " ";
cout << endl;
}

  1. 안녕~~!

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

forint i = 0 ; i < v2.size() ; i++)
cout << v2[i] << " ";
cout << endl;
}

  1. 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() ) );

forint i = 0 ; i < v2.size() ; i++)
cout << v2[i] << " ";
cout << endl;
}

  1. 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) );

forint i = 0 ; i < v2.size() ; i++)
cout << v2[i] << " ";
cout << endl;
}

  1. 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) );

forint i = 0 ; i < v2.size() ; i++)
cout << v2[i] << " ";
cout << endl;
}

  1. 안녕~~!

에러입니다. 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;
}

  1. 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_iteratorint >(cout, " " ) );
cout<< endl;

copy(v.begin(), v.end(), ostream_iteratorint >(cout, ", " ) );
cout<< endl;

}

  1. 10 20 30 40 50
    10, 20, 30, 40, 50,

ostream_iterator는 템플릿 클래스로 출력 반복자를 추상화한 클래스입니다. 템플릿 인자는 출력 타입이며(int) 생성자의 첫 번째 인자는 출력 스트림 객체, 두 번째 인자는 출력 값들 사이에 출력될 문자열입니다.

다음은 istream_iterator의 간단한 예제입니다.

#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( istream_iterator<int>(cin), istream_iterator<int>(), ostream_iterator< int >(cout, "," ) );
cout<< endl;
}

  1. 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는 조금 어려운 내용이 될 수도...

수고하셨습니다. 꾸벅!

반응형

+ Recent posts