레필리아
copy()와 특별한 이터레이터
레필리아
레필리아의 잡동사니
레필리아
전체
오늘
어제
  • 전체보기 (151)
    • 개발 공간 (1)
      • 매크로 (1)
    • 컴퓨터공학 리서치 (23)
      • 공개 (23)
      • 비공개 (0)
    • 컴퓨터공학 기초 (70)
      • Computer architectur.. (0)
      • Embedded system (6)
      • Operating system (0)
      • Database (2)
      • C.C++ (32)
      • Network (0)
      • Java (12)
      • 문제 풀이 (18)
    • 창고 (57)
      • 미분류 (57)
      • 유틸리티 (0)
      • 쓰레기통 (0)
      • ESLAB (0)

블로그 메뉴

  • 홈
  • 태그
  • 미디어로그
  • 위치로그
  • 방명록

공지사항

인기 글

태그

  • MSP430F5437

최근 댓글

최근 글

hELLO · Designed By 정상우.
컴퓨터공학 기초/C.C++

copy()와 특별한 이터레이터

2010. 10. 8. 22:29

★ 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
'컴퓨터공학 기초/C.C++' 카테고리의 다른 글
  • assert
  • 문자열 검색 함수 - strchr(), strrchr(), strstr(), strspn(), strcspn(), strpbrk()
  • 이터레이터(iterator)
  • C++ 문자열 자르기 (string)
레필리아
레필리아
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.