★ copy()
→ 하나의 컨테이너에서 특정 범위의 데이터를 다른 컨테이너로 복사하는 알고리즘
인수 1, 2 : [인수1, 인수2) 의 범위로 이터레이터를 인수로 넣음. (포인터도 가능)
인수 3 : 해당 이터레이터 지점부터 해서 데이터를 덮어씌운다.
→ 이 알고리즘의 주의사항은 인수 3에 넣어지는 지점에 삽입하는 것이 아니라 기존 데이터 위에 덮어 씌운다는 것이다. 또한 인수 3에 복사를 할때 자동으로 공간 할당을 해주지 않기 때문에 인수 1~2 범위 데이터를 넣을 수 있는 충분한 공간이 필요하다. 그렇지 않으면 할당 받지 않는 지점에 데이터를 덮어 씌우므로 런타임 에러를 유발하게 할 것이다.
→ copy() 는 다음과 같이 쓸 수 있다.
vector<int> test( 10 );
int iArray[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
copy( iArray, iArray + 10, test.begin() );
// test에 0~9가 들어간다.
★ ostream_iterator
→ 출력 이터레이터 개념의 모델. 이곳에 이터레이터를 copy() 함수로 복사하면 화면에 바로 출력이 가능하다.
→ 이것을 선언하기 위해서는 <iterator> 헤더를 인클루드 시켜야 한다.
ostream_iterator<int, char> out_iter( cout, " " );
→ ostream_iterator는 템플릿 전달인수가 2개 필요하다.
전달인수 1 : 출력 스트림으로 보내는 데이터 타입 즉, (위에서는)out_iter에 넣어야 되는 타입은 바로 이 인수타입(위에서는 int)이어야 한다.
전달인수 2 : 출력 스트림이 사용하는 문자형(위에서는 char). wchar_t가 될 수도 있다.
→ 생성자에는 인수 2개가 명시되어야 한다.
인수1 : 사용할 출력스트림. cout을 쓰면 out_iter에 데이터를 복사시 화면에 출력이 되지만 cout 대신 파일 출력 스트림을 써서 화면이 아닌 파일에 출력하게 할 수도 있다.
인수2 : 출력 스트림에 데이터를 보낼시 끝에 해당 데이터가 붙어서 보내지게 된다. 위의 경우는 띄어쓰기를 표시하고 있다.
→ 선언 이후 아래와 같이 사용 가능하다.
*out_iter++ = 15;
// 화면에 15 가 출력
→ 출력 스트림에 15를 보내어 15 가 출력되게 한다. (그냥 15만 출력되는것이 아니라 15에 띄어쓰기 문자까지 같이 출력된다.)
( 그 이후 ++이 하는 역활은 자세하게는 모르겠습니다. ㅠ.ㅠ )
→ copy() 알고리즘을 이용할 수도 있다.
copy( test.begin(), test.end(), out_iter );
→ 결과는 0 1 2 3 4 5 6 7 8 9 이렇게 출력된다. copy()를 통해 출력 스트림에 보낼시 이터레이터가 가리키는 원소 하나마다 띄어쓰기가 적용된다는 것을 알아두자.
copy( test.begin(), test.end(), ostream_iterator<int, char>( cout, " " ) );
→ 위와 같이 함수 내에서 익명의 이터레이터를 쓸 수도 있다.
★ istream_iterator
→ ostream_iterator 와는 반대 개념으로 이것은 copy()에서 이렇게 쓴다.
copy( istream_iterator<int, char>( cin ),
istream_iterator<int, char>(), test.begin() );
→ 이것의 첫번째 템플릿 데이터 인수는 읽을 데이터 타입이고, 두번째 템플릿 데이터 인수는 입력 스트림에 사용되는 문자 데이터를 나타낸다.
→ 생성자 전달인자 cin은 입력 스트림을 cin으로 쓰겠다는 것이지만 copy() 두번째 인수인 생성자 인수가 없다는 것은 입력의 실패(파일의 끝 또는 데이터 타입 불일치)를 나타낸다. 즉, 위 함수는 정수외의 다른 입력이 들어올 때까지 입력 스트림으로 데이터를 받는다는 것을 나타낸다.
★ reverse_iterator
→ 전에도 설명한 적이 있는 리버스 이터레이터다.
++ 연산은 일반 이터레이터의 --, -- 연산은 일반 이터레이터의 ++ 연산과 같은 특징을 지니며, 관련 메서드로...
rbegin()은 일반 컨테이너의 past-the-end 지점을 reverse_iterator 타입으로 리턴하고,
rend()는 일반 컨테이너의 첫번째 원소지점을 reverse_iterator 타입으로 리턴한다.
→ 여기서 아주 중요한 점이 있는데 바로 * 연산자이다.
그냥 이터레이터에서는 * 연산자가 해당 이터레이터 지점의 원소를 나타내는데, 리버스 이터레이터에서의 * 연산자는 (실제순서로) 현재 지점의 바로 이전 지점의 원소를 나타낸다는 것이다.
vector<int>::reverse_iterator rev_it;
rev_it = test.rbegin();
// test에는 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 가 들어있고, rev_it는 현재 past-the-end 즉, 9 바로 다음 지점을 가리킬 것이다.
cout << *rev_it << endl;
// rev_it의 이전 지점 원소인 9가 출력된다.
→ 이 때문에 for문이나 copy() 등에서 인수를 이터레이터 대신 reverse_iterator로 써도 문제가 생기지 않는다. 하지만 위의 사항은 반드시 알아두어야 할 것이다.
★ insert_iterator
→ 이 이터레이터를 copy()의 인수 3에 넣어서 통해 1~2지점의 데이터를 복사시, insert_iterator는 이것을 그냥 덮어 씌우는 것이 아니라, 삽입을 해준다. 자동으로 공간할당이 이루어지기 때문에 인수 3에 해당하는 컨테이너의 값을 덮어버린다던가 메모리 침범등의 문제를 해결 할 수가 있게 된다.
→ 선언은 이와 같이 한다. <iterator>가 인클루드 되어야 한다.
vector<int> test2;
insert_iterator< vector<int> > ins_it( test2, test2.begin() );
→ 여기서 들어가는 템플릿 데이터형 인수는 삽입하게 될 컨테이너 타입이다.
위의 경우는 vector<int> 타입인데 이런 형태로 넣어야 한다는 것을 의미한다. 또한 위에 같이 > > 사이에 반드시 공백을 두어 >> 연산자와 혼동하게 하면 안된다.
→ 또한 생성자로 인수가 두 개가 들어간다.
인수1 : 삽입하고자 하는 컨테이너. (타입이 아니라 선언된 실제 컨테이너 객체를 뜻한다.)
인수2 : 인수1의 컨테이너에서 삽입하고자 하는 부분을 이터레이터로 명시한다. 인수2 이터레이터 지점에 있던 원래 원소는 뒤로 멸려나고 삽입된다.
→ 사용법은 다음과 같이 매우 간단하다.
copy( test.begin(), test.end(), ins_it );
→ 선언시 생성자에서 명시한 위치인 test2 의 앞부분에 test의 모든 내용을 삽입한다.
★ back_insert_iterator
→ insert_iterator 는 지정된 위치에 데이터를 삽입하는 데에 비해 해당 이터레이터는 무조건 컨테이너의 후미에 데이터가 삽입된다는 특징을 지녔다. 그러므로 insert_iterator와의 차이점은 back_insert_iterator는 생성자에 인수2가 없다는 것이다. 그외의 템플릿 데이터형 전달인수나 생성자의 인수1의 역활은 같다.
→ 단, 주의점은 back_insert_iterator를 쓰기 위해서는 선언시 명시한 컨테이너 타입이 반드시 push_back() 함수를 지원해여야 한다는 것이다. 왜냐하면, back_insert_iterator는 컨테이너 끝부분에 대한 삽입을 고정시간으로 빠르게 수행하는 역활을 하는데, 만약 push_back()을 지원하지 않는 컨테이너는 끝부분에 대한 삽입이 고정시간이 아니다. 즉, push_back()의 역활을 제대로 수행할 수 없기 때문에 back_insert_iterator를 사용하지 못한다.
→ 하지만 만약 컨테이너가 push_back() 이 가능하고 마지막 부분 삽입을 주로 하게 된다면 insert_iterator 대신 back_insert_iterator를 사용하여 효율적인 속도향상을 도모할 수 있을 것이다.
★ front_insert_iterator
→ back_insert_iterator 와는 반대로 이것은 컨테이너 전방에 고정시간으로 데이터를 삽입하는 이터레이터다. 템플릿 전달인자, 생성자 인수1 또한 back_insert_iterator 와 역활이 같다.
→ 하지만 back_insert_iterator와 비슷하게 front_insert_iterator는 컨테이너가 push_front()를 지원하지 않으면 쓸 수 없다. 확실한 케이스 중 하나로 vector가 있다. front_insert_iterator의 전달인자로 vector를 쓰고 copy() 등의 알고리즘을 사용시 컴파일 에러가 되는 것을 확인 할 수 있을 것이다.
▶ 이 부분은 중간에 그냥 넘어갔던 부분중 하나였습니다. ㅇㅅㅇ. 이 부분에 대한 파악이 잘 안되니 후에 나올 결합 컨테이너에 대한 설명이 잘 안될 것 같더군요. 위의 삽입 이터레이터들은 copy() 뿐만 아니라 결합 컨테이너에서도 쓰이는 부분이 다소 있습니다. 유념해 주세요 ^^
'컴퓨터공학 기초 > C.C++' 카테고리의 다른 글
assert (0) | 2010.12.12 |
---|---|
문자열 검색 함수 - strchr(), strrchr(), strstr(), strspn(), strcspn(), strpbrk() (0) | 2010.10.11 |
이터레이터(iterator) (0) | 2010.10.08 |
C++ 문자열 자르기 (string) (0) | 2010.10.03 |
strtok() 함수를 이용한 연속 토큰 추출 (0) | 2010.10.03 |