Turbo-C
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
터보-C 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
Lua 게시판
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C/C++ 강좌/문서
[41] (12) STL ( Standard Template Library )
남병철.레조 [lezo] 19650 읽음    2009-06-21 12:39


[목차]

(1) STL 소개
(2) 알고리즘
(3) 순차 컨테이너
(4) 반복자
(5) 전문화 반복자
(6) 연관성 컨테이너










(1) STL 소개

    * 컨테이너 : 저장된 데이터를 메모리에서 체계화하는 방법.

    * 알고리즘 : 데이터를 여러 방법으로 처리하기 위해 컨테이너에 적용하는 절차.
      Ex) 정렬, 복사, 검색, 병합 등

    * 반복자 : 포인터 개념을 일반화한 것으로 컨테이너의 원소들을 가리키며 알고리즘을
               컨테이너와 연결해주는 STL의 심장부이다.

    <순차컨테이너 특징>
    -> 한 줄로 시각화할 수 있는 원소의 집합을 저장한다.
    =============================================================================================
    컨테이너           특징                          장단점
    =============================================================================================
    일반 C++배열       고정된 크기                   빠른 임의 접근(인덱스 번호로)
                                                     도중 삽입.삭제가 느림
                                                     실행 시간에 크기를 바꿀수 없다.

    벡터               위치 변경, 확장 배열          빠른 임의 접근(인덱스 번호로)
                                                     도중 삽입.삭제가 느림
                                                     끝에서 빠른 삽입.삭제 가능

    목록               이중 연결 목록                임의 위치에 빠른 삽입.삭제 가능
                                                     양 끝에서 빠르게 접근 가능
                                                     임의 접근 속도 느림

    디큐               벡터와 비슷함                 빠른 임의 접근(인덱스 번호로)
                       양끝에서 접근 가능            도중 삽입.삭제가 느림
                                                     시작 및 끝 위치에서 빠르게 삽입.삭제(푸시,팝)가능
    =============================================================================================



    <연관성 컨테이너 특징>
    -> 순서적이 아니라, 키를 사용하여 데이터에 접근한다.
    =============================================================================================
    컨테이너           특징                          장단점
    =============================================================================================
    맵                 키를 원소와 연계시킴          빠른 임의 접근(인덱스 번호로)
                       값 하나에 한 키만 허용        키가 균등하게 분포되지 않을 경우는 비능률적임

    멀티맵             키를 원소에 연계시킴          빠른 임의 접근(인덱스 번호로)
                       여러 키 값이 허용됨           키가 균등하게 분포되지 않을 경우는 비능률적임

    세트               키 자체만을 저장              빠른 임의 접근(인덱스 번호로)
                       값 하나에 한 키만 허용        키가 균등하게 분포되지 않을 경우는 비능률적임

    멀티세트           키 자체만 저장                빠른 임의 접근(인덱스 번호로)
                       여러 키 값이 허용됨           키가 균등하게 분포되지 않을 경우는 비능률적임
    =============================================================================================



    <구성원 함수>
    -> 아래는 이름과 목적(실제 구현은 아님)이 모든 컨테이너에 공통으로 적용되고 자주 사용되는
       몇몇 구성원 함수를 나타낸다.
    =============================================================================================
    이름               목적	
    =============================================================================================
    size()             컨테이너의 항목 수를 리턴한다.
    empty()            컨테이너가 비어 있으면 참을 리턴한다.
    max_size()         가장 큰 컨테이너의 크기를 리턴한다.
    begin()            컨테이너에서 정방향으로 반복하기 위한 컨테이너의 시작 위치에 대한 반복자를
                       리턴한다.
    end()              컨테이너의 끝 다음 위치에 대한 반복자를 리턴하며, 정방향 반복을 끝내기 위해
                       사용된다.
    rbegin()           컨테이너에서 역방향으로 반복하기 위한 컨테이너의 끝에 대한 역 반복자를 리턴
                       한다.
    rend()             컨테이너의 시작 위치에 대한 역 반복자를 리턴하며, 역방향 반복을 끝내기 위해
                       사용된다.
    =============================================================================================



    
    위 에서 본 기본적인 컨테이너들을 사용하여 다른 종류의 컨테이너를 만들 수 있다.
    STL에 구현된 ADT는 스택, 큐, 우선 큐(priority que)이다.
    (아래는 추상 데이터형과 그 구현에 사용할 수 있는 순차적 컨테이너들이다.)
    =============================================================================================
    컨테이너           구현                    특징
    =============================================================================================
    스택               벡터, 목록, 디큐        한쪽에서만 삽입(push)하고 꺼낸다(pop).
    큐                 목록, 디큐              한쪽에서 삽입(push)하고 반대쪽에서 꺼낸다(pop).
    우선 큐            목록, 디큐              한쪽에서 임의 순서로 삽입(push)하고 반대쪽에서 정
                                               렬된 순서로 꺼낸다(pop).
    =============================================================================================
    Ex) 디큐를 이용해 int 스택을 구현한 예
       stack< deque > astak;



    <알고리즘>
    -> 알고리즘은 컨테이너(들)의 항목에 무언가 일을 하는 함수이다.
       STL의 알고리즘은 대부분의 다른 컨테이너 라이브러리에서와 같이 구성원 함수나 컨테이너
       Class의 프렌드가 아니라 독립형 템플릿 함수이다.
       즉, Class가 특정 기본 함수를 포함한다면 개인적으로 만든 Class도 알고리즘에 적용할 수 있다.
    =============================================================================================
    알고리즘           목적
    =============================================================================================
    find               지정된 값과 같은 첫 번째 원소를 리턴한다.
    count              지정된 값을 가진 원소 수를 센다.
    equal              두 컨테이너의 내용들을 비교하고 모든 해당 원소들이 같으면 참을 리턴한다.
    search             한 컨테이너에서 또 다른 컨테이너의 같은 순서에 해당하는 값의 순서를 찾는다.
    copy               한 컨테이너의 값의 순서를 또 다른 컨테이너(또는 같은 컨테이너의 다른 위치)
                       에 복사한다.
    swap               한 위치의 값을 또 다른 위치의 값과 교환한다.
    iter_swap          한 위치의 값의 순서를 또 다른 위치의 값의 순서와 교환한다.
    fill               값을 위치의 순서에 복사한다.
    sort               컨테이너의 값들을 지정된 순서에 따라 정렬한다.
    merge              정렬된 두 원소의 범위를 결합하여 더 큰 정렬된 범위를 만든다.
    accumulate         어떤 범위의 원소들의 합계를 리턴한다.
    for_each           컨테이너의 각 원소에 대해 지정된 함수를 실행한다.
    =============================================================================================
    Ex) int 배열에 sort() 알고리즘 적용 예
        int arr[8] = { 42, 31, 7, 80, 2, 26, 19, 75 };
        sort( arr, arr+8 );



    <반복자>
    -> 반복자는 컨테이너의 각 데이터 항목(원소)에 접근하기 위해 사용하는 포인터와 같은 엔티티이다.
       반복자는 원소별로 차례로 이동시키는데 흔히 사용된다.
       3대 반복자 : 정방향, 양방향, 임의 접근
       전문화 반복자 : 입력 반복자, 출력 반복자
    =============================================================================================
    반복자         읽기/쓰기        저장       방향               접근
    =============================================================================================
    임의 접근      읽기와 쓰기      가능       정방향과 역방향    임의
    양방향         읽기와 쓰기      가능       정방향과 역방향    선형
    정방향         읽기와 쓰기      가능       정방향만           선형
    출력           쓰기 전용        불가능     정방향만           선형
    입력           읽기 전용        불가능     정방향만           선형
    =============================================================================================



    [참고]
    STL 컴파일 오류중에서
    Conversion may lose significant digits는 무시하거나 없애도 좋은것으로 밝혀졌다.





(2) 알고리즘
    - 알고리즘은 STL 컨테이너에서 작동하도록 설계되었지만, 일반 C++ 배열에서도 적용할 수 있다.



    * find()
      - 컨테이너에서 지정된 값을 가진 첫 번째 원소를 찾는다.
//---------------------------------------------------------------------------
// 작성일 : 2002.08.08
// 제  목 : STL find() 알고리즘
// 작성자 : 남병철
//---------------------------------------------------------------------------

#include 
#include 

//---------------------------------------------------------------------------

int arr[] = { 11, 22, 33, 44, 55, 66, 77, 88 };

//---------------------------------------------------------------------------

void main()
{
	int* ptr;
	// find( 시작포인터, 끝다음포이터, 찾는 값 );
	ptr = find( arr, arr+8, 33 );
	cout << "First object with value 33 found at offset "
		 << ( ptr - arr ) << endl; // 처음에서 찾고자하는 곳까지의 거리가 찍힘
}

//---------------------------------------------------------------------------
* count() - 컨테이너에서 지정된 값을 가진 원소 수를 세는 알고리즘. 개수를 리턴하는 대신 참조로 int값을 증가하여 개수를 센다. 요점 : 기존 수에 개수를 참조로 더하는 것은 무언가를 이미 센 후 이전 것에 새 개수를 더하고자 할 때 유용하다.
//---------------------------------------------------------------------------
// 작성일 : 2002.08.08
// 제  목 : STL count() 알고리즘
// 작성자 : 남병철
//---------------------------------------------------------------------------

#include 
#include 

//---------------------------------------------------------------------------

int arr[] = { 33, 22, 33, 44, 33, 55, 66, 77 };

//---------------------------------------------------------------------------

void main()
{
	int n = 0;
	// count( 시작포인터, 끝다음포이터, 비교 값, 비교된 개수 );
	count( arr, arr+8, 33, n );
	cout << "There are " << n << " 33's in arr." << endl;
}

//---------------------------------------------------------------------------
* sort() - 배열을 ascend 소트한다.
//---------------------------------------------------------------------------
// 작성일 : 2002.08.08
// 제  목 : STL sort() 알고리즘
// 작성자 : 남병철
//---------------------------------------------------------------------------

#include 
#include 

//---------------------------------------------------------------------------

int arr[] = { 45, 2, 22, -17, 0, -30, 25, 55 };

//---------------------------------------------------------------------------

void main()
{
	// sort( 시작포인터, 끝다음포이터 );
	sort( arr, arr+8 );

	for( int j = 0; j < 8; j++ )
		cout << arr[j] << ' ';
}

//---------------------------------------------------------------------------
* search() - 어떤 컨테이너에서 지정된 값의 순서를 또 다른 컨테이너 안에서 찾는다.
//---------------------------------------------------------------------------
// 작성일 : 2002.08.08
// 제  목 : STL search() 알고리즘
// 작성자 : 남병철
//---------------------------------------------------------------------------

#include 
#include 

//---------------------------------------------------------------------------

int source[] = { 11, 44, 33, 11, 22, 33, 11, 22, 44 };
int pattern[] = { 11, 22, 33 };

//---------------------------------------------------------------------------

void main()
{
	int* ptr;
	// search( 원본시작포인터, 원본끝다음포이터, 패턴시작포인터, 패턴끝다음포인터 );
	ptr = search( source, source+9, pattern, pattern+3 );

	// 원소3 즉, 4번째 원소에서 발견되었다.
	if( ptr == source+9 )
		cout << "No match found";
	else
		cout << "Match at " << ( ptr - source );
}

//---------------------------------------------------------------------------
* merge() - 세개의 컨테이너에 작용하여 두 원본 컨테이너의 원소를 대상 컨테이너에 병합하는 알고리즘을 나타낸다. 두 대상 데이터가 끼워넣어져 소트되어 들어간다.
//---------------------------------------------------------------------------
// 작성일 : 2002.08.08
// 제  목 : STL merge() 알고리즘
// 작성자 : 남병철
//---------------------------------------------------------------------------

#include 
#include 

//---------------------------------------------------------------------------

int src1[] = { 2, 3, 4, 6, 8 };
int src2[] = { 1, 3, 5 };
int dest[8];

//---------------------------------------------------------------------------

void main()
{
	// merge( 원본1시작포인터, 원본1끝다음포이터, 원본2시작포인터, 원본2끝다음포인터, 대상시작포인터 );
	merge( src1, src1+5, src2, src2+3, dest );

	for( int j = 0; j < 8; j++ )
		cout << dest[j] << ' ';
}

//---------------------------------------------------------------------------
* 함수 객체 함수 객체는 사용자가 보면 템플릿 함수와 비슷해 보이지만 사실 겹지정 ()연산자인 단일 구성원 함수를 가진 템플릿 Class 객체이다. 수의 배열을 내림차순으로 정렬
//---------------------------------------------------------------------------
// 작성일 : 2002.08.13
// 제  목 : STL sort() 내림차순 알고리즘
// 작성자 : 남병철
//---------------------------------------------------------------------------

#include 
#include 
#include 

//---------------------------------------------------------------------------

float fdata[] = { 19.2, 87.4, 33.6, 55.0, 11.5, 42.2 };

//---------------------------------------------------------------------------

void main()
{
	// float를 내림차순으로 정렬
	sort( fdata, fdata+6, greater() );


	for( int j = 0; j < 6; j++ )
		cout << fdata[j] << ' ';
}

//---------------------------------------------------------------------------
* 함수 객체를 대신하는 사용자 함수 작성 함수 객체는 C++ 기본자료형과 해당 연산자(+,<,&& 등)가 정의된 Class에서만 작용한다. 즉, char*에대해 일반적으로 < (비교연산자)가 정의 되지 않았지만 사용자 함수를 만들어 함수 객체 자리에 사용자 정의 함수를 대신 넣어도 된다.
//---------------------------------------------------------------------------
// 작성일 : 2002.08.13
// 제  목 : STL sort() 알파벳 사용자 정의 함수 사용하기
// 작성자 : 남병철
//---------------------------------------------------------------------------

#include 
#include 
#include 

//---------------------------------------------------------------------------

char* names[] = { "George", "Penny", "Estelle", "Don", "Mike", "Bob" };

bool alpha_comp( char*, char* );

//---------------------------------------------------------------------------

void main()
{
	// 알파벳 문자열 정렬
	sort( names, names+6, alpha_comp );

	for( int j = 0; j < 6; j++ )
		cout << names[j] << endl;
}

//---------------------------------------------------------------------------

bool alpha_comp( char* s1, char* s2 )
{
	return ( strcmp( s1, s2 ) < 0 ) ? true : false;
}

//---------------------------------------------------------------------------
* 인수에 _if 알고리즘 추가하기 _if로 끝나는 알고리즘은 함수 객체 나 함수를 predicate로 추가 매개변수를 갖는다. ex) find() 알고리즘은 객체의 데이터형에 대해 = 연산자가 정의되어 있어야하나 그렇지 않을경우 find_if()를 사용하여 =과 동일한 작동을하는 함수를 만들 수 있다. find_if 알고리즘은 배열의 모든 원소에 isDon() 함수를 적용한다. isDon()이 어떤 원소에 대해 true를 리턴하면, find_if()는 그 원소의 포인터(반복자)의 값을 리턴 한다. 그렇지 않으면 배열의 끝 다음 주소 포인터를 리턴한다. (count(), replace(), remove() 등 여러가지 다른 알고리즘도 _if버전을 가지고 있다.)
//---------------------------------------------------------------------------
// 작성일 : 2002.08.13
// 제  목 : 문자열의 배열에서 "Don"과 일치하는 이름을 찾는다.
// 작성자 : 남병철
//---------------------------------------------------------------------------

#include 
#include 

//---------------------------------------------------------------------------

char* names[] = { "George", "Estelle", "Don", "Mike", "Bob" };

bool isDon( char* );

//---------------------------------------------------------------------------

void main()
{
	char** ptr;
	
	// ptr은 주소 자체
	// *ptr은 ptr이 가르키는 주소의 문자열들
	// **ptr은 *ptr이 가리키는 문자열중 ptr에 해당하는 문자(값)
	ptr = find_if( names, names+5, isDon );

	cout << ptr << endl;           // %p 개념
	cout << *ptr << endl;          // %s 개념
	cout << **ptr << endl << endl; // %c 개념

	if( ptr == names+5 )
		cout << "Don is not on the list";
	else
		cout << "Don is element "
			 << (ptr-names)
			 << " on the list.";

}

//---------------------------------------------------------------------------

bool isDon( char* name )
{
	return ( strcmp( name, "Don" ) ) ? false : true;
}

//---------------------------------------------------------------------------
* for_each() 컨테이너의 모든 항목에 대해 무언가 일을 할 수 있게 한다. 프로그래머는 그 '무언가'를 결정하는 사용자 정의 함수를 작성해야 한다.
//---------------------------------------------------------------------------
// 작성일 : 2002.08.14
// 제  목 : for_each()
// 작성자 : 남병철
//---------------------------------------------------------------------------

#include 
#include 

//---------------------------------------------------------------------------

void main()
{
	float inches[] = { 3.5, 6.2, 1.0, 12.75, 4.33 };
	void in_to_cm( float );

	for_each( inches, inches+5, in_to_cm );
}

//---------------------------------------------------------------------------

void in_to_cm( float in )
{
	cout << ( in * 2.54 ) << ' ';
}

//---------------------------------------------------------------------------
* transform() 컨테이너의 모든 항목에 대해 무언가 일을 하고 결과값을 다른 컨테이너 (또는 같은 것)에 넣는다. 사용자 정의 함수가 각 항목에 대해 수행할 일을 결정한다. 리턴값은 대상 컨테이너의 것과 같아야 한다.
      
//---------------------------------------------------------------------------
// 작성일 : 2002.08.14
// 제  목 : transform()
// 작성자 : 남병철
//---------------------------------------------------------------------------

#include 
#include 

//---------------------------------------------------------------------------

void main()
{
	float inches[] = { 3.5, 6.2, 1.0, 12.75, 4.33 };
	float centi[5];
	float in_to_cm( float );

	transform( inches, inches+5, centi, in_to_cm );

	for( int j = 0; j < 5; j++ )
		cout << centi[j] << ' ';
}

//---------------------------------------------------------------------------

float in_to_cm( float in )
{
	return ( in * 2.54 );
}

//---------------------------------------------------------------------------
(3) 순차 컨테이너 * 백터(vector) 데이터를 삽입, 삭제할때 벡터의 크기를 키우고 줄여서 저장 장치 할당을 관리해 준다. 배열처럼 [] 겹지정 연산자를 사용해 원소에 임의접근 속도가 빠르다. 새 데이터를 백터 끝에 추가하는(push) 속도도 빠르다. (단, [] 연산자는 벡터의 크기를 벗어나서 읽고 쓰는건 안된다. 벡터 크기가 4인데 v[27]의 값을 읽고 쓰는건 않된다.) size() 구성원 함수는 현재 벡터에 들어있는 원소 수를 리턴하며 max_size() 구성원 함수는 컨테이너를 확장할 수 있는 최대 크기를 리턴 (컨테이너의 타입(int..), 메모리 및 운영체제에 따라 다르다.) 벡터는 언제나 메모리의 연속 영역을 차지한다. 즉, 벡터가 너무 커지면 그것이 들어갈 수있는 새 위치로 이동 될 수 있다. (capacity()는 벡터가 이동하지 않고 저장할 수 있는 원소 수를 리턴한다.)
//---------------------------------------------------------------------------
// 작성일 : 2002.08.15
// 제  목 : vector<>
// 작성자 : 남병철
//---------------------------------------------------------------------------

#include 
#include 

//---------------------------------------------------------------------------

void main()
{
	vector v; // 무인수 생성자로 벡터 객체 생성

	// 배열의 끝에 삽입
	v.push_back( 10 ); 
	v.push_back( 11 );
	v.push_back( 12 );
	v.push_back( 13 );

	// 임의 접근 삽입
	v[0] = 20;
	v[3] = 23;

	cout << "size = " << v.size() << endl;
	cout << "max_size = " << v.max_size() << endl;
	cout << "capacity = " << v.capacity() << endl;

	// 임의 접근 읽기
	for( int j = 0; j < v.size(); j++ )
		cout << v[j] << ' ';
}

//---------------------------------------------------------------------------
* vector의 구성원 함수 back() - 벡터의 마지막 원소값 리턴 push_back() - 벡터의 마지막에 원소 삽입 pop_back() - 벡터의 마지막 원소를 삭제 swap() - 한 벡터의 모든 데이타를 또다른 벡터의 모든 데이터와 교환하며 원소들의 순서는 그대로 유지된다. insert(), erase() - 컨테이너 임의 위치에서 원소를 삽입, 삭제한다.
//---------------------------------------------------------------------------
// 작성일 : 2002.08.15
// 제  목 : vector<>의 swap(), empty(), back(), pop_back()
// 작성자 : 남병철
//---------------------------------------------------------------------------

#include 
#include 

//---------------------------------------------------------------------------

void main()
{
	float arr[] = { 1.1, 2.2, 3.3, 4.4 };

	// 벡터를 배열로 초기화
	vector v1( arr, arr+4 );

	// 크기 4의 빈 벡터
	vector v2( 4 );


	// v1과 v2의 내용을 바꾼다.
	v1.swap( v2 );

	while( !v2.empty() )
	{
		cout << v2.back() << ' ';
		v2.pop_back();
	}
}

//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// 작성일 : 2002.08.15
// 제  목 : vector<>의 insert(), erase()
// 작성자 : 남병철
//---------------------------------------------------------------------------

#include 
#include 

//---------------------------------------------------------------------------

void main()
{
	int arr[] = { 100, 110, 120, 130 };
	vector v( arr, arr+4 );
	int j;

	cout << "\nBefore insertion : ";
	for( j = 0; j < v.size(); j++ )
		cout << v[j] << ' ';

	// 원소2(세번째)에 115를 삽입
	v.insert( v.begin()+2, 115 );

	cout << "\nAfter insertion : ";
	for( j = 0; j < v.size(); j++ )
		cout << v[j] << ' ';

	// 원소2(세번째)를 삭제
	v.erase( v.begin()+2 );

	cout << "\nAfter erasure : ";
	for( j = 0; j < v.size(); j++ )
		cout << v[j] << ' ';
}

//---------------------------------------------------------------------------
* 목록(list) STL의 list 컨테이너는 이중연결목록(double linked list)이다. 앞의 원소 및 뒤의 원소 모두의 주소를 가지고 있으므로 list의 앞뒤는 빠르게 접근 할 수 있다. 그러나 [] 연산자로 임의 접근은 할 수 없다. ([] 연산자가 가능하더라도 list를 훓어야 하기때문에 좋은 방법이 아니다. 마치 라이프 게임이나 오목에서 내가했던것 처럼 여러가지 비교를 하게되면 많은 시간을 허비하게된다.) 임의 접근을 하려면 벡터나 디큐여야한다. push_back() - list의 끝에 원소값을 추가 pop_back() - list의 끝 원소를 삭제 back() - list의 끝 원소를 리턴 push_front() - list의 앞에 원소값을 추가 pop_front() - list의 첫 원소값을 삭제 front() - list의 첫 원소값을 리턴 insert()와 erase() 구성원 함수는 반복자도 사용해야 하므로 반복자 이후로 미룬다. reverse() - 컨테이너 원소의 순서를 역순으로 바꾼다. merge() - 우측을 좌측에 병합하면서 오름차순 정렬한다. unique() - 중복되는 인접 원소쌍을 찾아 첫번째것을 제외한 모든것을 삭제한다.
      
//---------------------------------------------------------------------------
// 작성일 : 2002.08.15
// 제  목 : list<>
// 작성자 : 남병철
//---------------------------------------------------------------------------

#include 
#include 

//---------------------------------------------------------------------------

void main()
{
	list ilist;

	ilist.push_back( 30 );
	ilist.push_back( 40 );
	ilist.push_front( 20 );
	ilist.push_front( 10 );

	int size = ilist.size();

	for( int j = 0; j < size; j++ ) {
		cout << ilist.front() << ' ';
		ilist.pop_front();
	}
}

//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// 작성일 : 2002.08.16
// 제  목 : list<>의 reverse(), merge(), unique()
// 작성자 : 남병철
//---------------------------------------------------------------------------

#include 
#include 

//---------------------------------------------------------------------------

void main()
{
	int arr1[] = { 40, 30, 20, 10 };
	int arr2[] = { 15, 20, 25, 30, 35 };

	list list1( arr1, arr1+4 );
	list list2( arr2, arr2+5 );

	// list1의 원소를 뒤바꿈
	list1.reverse();
	// list2를 list1에 병합
	list1.merge( list2 );
	// 중복되는 인접값 20과 30을 삭제
	list1.unique();

	int size = list1.size();
	for( int j = 0; j < size; j++ ) {
		cout << list1.front() << ' ';
		list1.pop_front();
	}
}

//---------------------------------------------------------------------------
* 디큐 디큐는 벡터의 변형이다. [] 연산자를 이용한 임의접근이 가능할 뿐만아니라 앞,뒤에서 삽입, 삭제가 가능하다. (push_front(), pop_front(), front()를 지원하는 양방향 벡터이다.) 디큐는 여러 비연속 영역에 저장되므로 capacity()는 지원하지 않는다.
//---------------------------------------------------------------------------
// 작성일 : 2002.08.16
// 제  목 : deque<>
// 작성자 : 남병철
//---------------------------------------------------------------------------

#include 
#include 

//---------------------------------------------------------------------------

void main()
{
	deque deq;

	// 컨테이넌 뒷부분에 삽입
	deq.push_back( 30 );
	deq.push_back( 40 );
	deq.push_back( 50 );

	// 컨테이너 앞부분에 삽입
	deq.push_front( 20 );
	deq.push_front( 10 );

	// 3번째 원소에 값 변경
	deq[2] = 33;

	for( int j = 0; j < deq.size(); j++ )
		cout << deq[j] << ' ';
}

//---------------------------------------------------------------------------
(4) 반복자 반복자는 스마트 포인터로서의 역할, 알고리즘과 컨테이너 사이의 연결 역할을 한다. [스마트 포인터] 일반 C++ 배열에서도 ++ 연산자를 사용하여 원소를 이동할 수 있지만 컨테이너가 링크드 리스트처럼 연속적 공간에 놓이지 않게된다면 ++ 연산자로 단순히 다음 데이터를 가리킬수 없게 된다. STL에서는 이러한 문제를 해결한 스마트 포인터 Class를 iterator라고 하며 그 객체를 생성하므로써 사용한다. [인터페이스로서 반복자] 정교한 순서대로 5가지의 반복자 종류가 있다. 1. 입력, 출력 반복자 : 컨테이너를 정방향으로 접근하며 항목을 읽고 쓴다. 2. 정방향 반복자 : 입력, 출력 반복자의 기능을 합한것이다.(정방향 탐색, 읽기 쓰기) 3. 양방향 반복자 : 정방향과 역방향으로 접근하며 읽고 쓸수있다. 4. 임의접근 반복자 : 양방향의 기능 + 임의접근이 가능하다. [각 반복자 부류의 기능] ============================================================================================= 반복자 정방향탐색 읽기 쓰기 역방향탐색 임의접근 ============================================================================================= ++ value=*i *i=value -- [n] 임의 접근 0 0 0 0 0 양방향 0 0 0 0 정방향 0 0 0 출력 0 0 입력 0 0 ============================================================================================= [케이블을 컨테이너에 접속하기] 기본 STL 컨테이너만 사용한다면 두종류의 반복자만 사용한다. 벡터, 디큐는 임의 접근 반복자 목록, 세트, 멀티세트, 맵, 멀티맵은 양방향 반복자 이러한 자동 선택 과정은 ITERATOR.H 및 다른 헤더 파일의 깊은곳에서 이루어진다. ============================================================================================= 반복자 벡터 목록 디큐 세트 멀티세트 맵 멀티맵 ============================================================================================= 임의 접근 0 0 양방향 0 0 0 0 0 0 0 정방향 0 0 0 0 0 0 0 출력 0 0 0 0 0 0 0 입력 0 0 0 0 0 0 0 ============================================================================================= [알고리즘에 케이블 접속하기] 반복자(케이블)가 한쪽인 컨테이너에 접속되는것을 알아보았다. 반대쪽인 알고리즘에는 어떻게 접속되는지 살펴본다. (아래에 표시된것은 최소사양이므로 보다 일반적 반복자 또한 적용된다.) (임의 접근 반복자를 요구하지 않는 모든 알고리즘은 모든 종류의 STL 컨 테이너에서 작동한다.) ================================================================== 알고리즘 입력 출력 정방향 양방향 임의접근 ================================================================== for_each 0 find 0 count 0 copy 0 0 replace 0 unique 0 reverse 0 sort 0 nth_element 0 merge 0 0 accumulate 0 ==================================================================
//---------------------------------------------------------------------------
// 작성일 : 2002.08.19
// 제  목 : 반복자 사용하기 1
// 작성자 : 남병철
//---------------------------------------------------------------------------

#include 
#include 

//---------------------------------------------------------------------------

void main()
{
	int arr[] = { 2, 4, 6, 8 };
	list iList( arr, arr+4 );
	list::iterator it; // int list의 반복자 선언

	for( it = iList.begin(); it != iList.end(); it++ )
		cout << *it << ' ';
}

//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// 작성일 : 2002.08.19
// 제  목 : 반복자 사용하기 2
// 작성자 : 남병철
//---------------------------------------------------------------------------

#include 
#include 

//---------------------------------------------------------------------------

void main()
{
	list iList(5);
	list::iterator it;
	int data = 0;

	for( it = iList.begin(); it != iList.end(); it++ )
		*it = data += 2;

	for( it = iList.begin(); it != iList.end(); it++ )
		cout << *it << ' ';
}

//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// 작성일 : 2002.08.19
// 제  목 : find() 알고리즘에 반복자 사용하기
// 작성자 : 남병철
//---------------------------------------------------------------------------

#include 
#include 

//---------------------------------------------------------------------------

void main()
{
	list iList( 5 );
	list::iterator it;
	int data = 0;

	for( it = iList.begin(); it != iList.end(); it++ )
		*it = data += 2;

	// 수 8을 찾음
	it = find( iList.begin(), iList.end(), 8 );

	if( it != iList.end() )
		cout << "\nFound 8";
	else
		cout << "\nDid not find 8.";
}

//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// 작성일 : 2002.08.19
// 제  목 : copy() 알고리즘에 반복자 사용하기
// 작성자 : 남병철
//---------------------------------------------------------------------------

#include 
#include 
#include 

//---------------------------------------------------------------------------

void main()
{
	int beginRange, endRange;
	int arr[] = { 11, 13, 15, 17, 19, 21, 23, 25, 27, 29 };
	vector v1( arr, arr+10 );
	vector v2( 10 );

	cout << "Enter range to be copied (example : 2 5) : ";
	cin >> beginRange >> endRange;

	vector::iterator it1 = v1.begin() + beginRange;
	vector::iterator it2 = v1.begin() + endRange;
	vector::iterator it3;

	// v1에서 it1 ~ it2의 범위를 v2에 복사
	// it3 -> it1 ~ (it2 - 1)까지 복사된후 그 다음 값
	// 3~6을 입력하면 3~5를 복사한후 v2의 4번째 자리(v1의 6번째 항목이 들어갈 자리)를 리턴
	it3 = copy( it1, it2, v2.begin() );

	it1 = v2.begin();
	while( it1 != it3 )
		cout << *it1++ << ' ';
}

//---------------------------------------------------------------------------
(5) 전문화 반복자 전문화 반복자에는 크게 두가지가 있다. * 반복자의 작동을 바꿀 수 있는 반복자 어댑터 * 입력과 출력 스트림이 반복자처럼 하게하는 스트림 반복자 * 반복자 어댑터 - 역 반복자 : 컨테이너를 역으로 반복할 수 있다. - 삽입 반복자 : copy(), merge()등의 알고리즘들의 작동을 기존 데이터를 덮어쓰지 않고 컨테이너에 삽입하도록 바꾼다. - 원본 저장장치 반복자 : 출력 반복자가 초기화되지 않은 메모리에 저장할 수 있게 해 주지만 그것은 특수한 상황에 사용되므로 여기선 생략한다. * 역 반복자 역으로 반복하려면 역 반복자를 사용해야 한다. 역 반복자를 사용할 때에는 구성원 함수 rbegin(), rend()를 사용해야 한다.
//---------------------------------------------------------------------------
// 작성일 : 2002.08.26
// 제  목 : 역 반복자 사용하기
// 작성자 : 남병철
//---------------------------------------------------------------------------

#include 
#include 

//---------------------------------------------------------------------------

void main()
{
	int arr[] = { 2, 4, 6, 8, 10 };
	list iList( arr, arr+5 );

	// 역 반복자
	list::reverse_iterator revit;

	// list에서 역으로 반복하며 화면 출력
	revit = iList.rbegin();
	while( revit != iList.rend() )
		cout << *revit++ << ' ';
}

//---------------------------------------------------------------------------
* 삽입 반복자 copy()와 같은 일부 알고리즘은 대상 컨테이너의 기존 내용을 덮어쓴다.
//---------------------------------------------------------------------------
// 작성일 : 2002.08.27
// 제  목 : 디큐를 이용한 정상 복사
// 작성자 : 남병철
//---------------------------------------------------------------------------

#include 
#include 
#include 

//---------------------------------------------------------------------------

void main()
{
	// d1 초기화
	int arr1[] = { 1, 3, 5, 7, 9 };
	deque d1( arr1, arr1+5 );

	// d2 초기화
	int arr2[] = { 2, 4, 6, 8, 10 };
	deque d2( arr2, arr2+5 );
	
	// d1을 d2에 복사
	copy( d1.begin(), d1.end(), d2.begin() );

	// d2를 화면에 출력
	for( int j = 0; j < d2.size(); j++ )
		cout << d2[j] << ' ';
}

//---------------------------------------------------------------------------
* copy()가 이전 것을 덮어 쓰지 않고 이전 것도 남겨 둔 채 새 원소를 컨테이너에 삽입 하려면 삽입 반복자를 사용한다. 삽입 반복자에는 3가지가 있다. - back_inserter : 새 데이터를 끝에 삽입 - front_inserter : 새 데이터를 시작 위치에 삽입 - inserter : 새 데이터를 지정한 위치에 삽입
//---------------------------------------------------------------------------
// 작성일 : 2002.08.27
// 제  목 : 삽입 반복자 back_inserter 버전
// 작성자 : 남병철
//---------------------------------------------------------------------------

#include 
#include 
#include 

//---------------------------------------------------------------------------

void main()
{
	// d1을 초기화
	int arr1[] = { 1, 3, 5, 7, 9 };
	deque d1( arr1, arr1+5 );

	// d2를 초기화
	int arr2[] = { 2, 4, 6 };
	deque d2( arr2, arr2+3 );

	// back_inserter는 push_back() 구성원 함수를 사용하여 새 항목을 대상 컨테이너
	// d2의 끝에 기존 항목 다음에 삽입한다.
	copy( d1.begin(), d1.end(), back_inserter( d2 ) );

	cout << "\nd2 : ";
	for( int j = 0; j < d2.size(); j++ )
		cout << d2[j] << ' ';
}

//---------------------------------------------------------------------------
* 벡터는 push_front 구성원 함수를 가지고 있지 않으므로 front_insert는 벡터에 사용할 수 없다.
//---------------------------------------------------------------------------
// 작성일 : 2002.08.27
// 제  목 : 삽입 반복자 front_inserter 버전
// 작성자 : 남병철
//---------------------------------------------------------------------------

#include 
#include 
#include 

//---------------------------------------------------------------------------

void main()
{
	// d1을 초기화
	int arr1[] = { 1, 3, 5, 7, 9 };
	deque d1( arr1, arr1+5 );

	// d2를 초기화
	int arr2[] = { 2, 4, 6 };
	deque d2( arr2, arr2+3 );

	// 정방향 삽입자
	// 새 항목은 컨테이너의 앞부분에 push_front()구성원 함수로 삽입된다.
	// 결국 순서가 뒤바뀌어 삽입되는격이다.
	copy( d1.begin(), d1.end(), front_inserter( d2 ) );

	cout << "\nd2 : ";
	for( int j = 0; j < d2.size(); j++ )
		cout << d2[j] << ' ';
}

//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// 작성일 : 2002.08.27
// 제  목 : 삽입 반복자 inserter 버전
// 작성자 : 남병철
//---------------------------------------------------------------------------

#include 
#include 
#include 

//---------------------------------------------------------------------------

void main()
{
	// d1을 초기화
	int arr1[] = { 1, 3, 5, 7, 9 };
	deque d1( arr1, arr1+5 );

	// d2를 초기화
	int arr2[] = { 2, 4, 6 };
	deque d2( arr2, arr2+3 );

	// inserter
	// 임의의 원소부터 시작하여 새항목을 삽입할 수 있다.
	// inserter는 컨테이너의 insert() 구성원 함수를 사용하므로 원소들의 순서는 뒤바뀌지
	// 않는다.
	copy( d1.begin(), d1.end(), inserter( d2, d2.begin() ) );

	cout << "\nd2 : ";
	for( int j = 0; j < d2.size(); j++ )
		cout << d2[j] << ' ';
}

//---------------------------------------------------------------------------
* 스트림 반복자 스트림 반복자는 파일과 입출력 장치(cin과 cout)를 반복자처럼 취급할 수 있게 해준다. 입력 반복자와 출력 반복자 부류의 주 목적은 스트림 반복자를 Class를 지원하는 것이다. - ostream_iterator 출력 반복자를 지정하는 모든 알고리즘의 인수로 사용할 수 있다. 첫번째 인수는 해당 타입값(int)을 기록할 대상 스트림이고 두번째 인수는 각 값의 다음에 표시되는 문자열 값이다.
//---------------------------------------------------------------------------
// 작성일 : 2002.08.27
// 제  목 : ostream_iterator cout 출력
// 작성자 : 남병철
//---------------------------------------------------------------------------

#include 
#include 
#include 

//---------------------------------------------------------------------------

void main()
{
	int arr[] = { 10, 20, 30, 40, 50 };
	list iList( arr, arr+5 );

	// ostream_iterator 지정
	ostream_iterator ositer( cout, "--" );
	cout << "\nContents of list : ";

	// list를 화면 출력( ostream_iterator 이용한 cout 출력 )
	copy( iList.begin(), iList.end(), ositer );
}

//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// 작성일 : 2002.08.27
// 제  목 : ostream_iterator file 출력
// 작성자 : 남병철
//---------------------------------------------------------------------------

#include 
#include 
#include 

//---------------------------------------------------------------------------

void main()
{
	int arr[] = { 11, 21, 31, 41, 51 };
	list iList( arr, arr+5 );

	// 파일 객체 생성
	ofstream outfile( "ITER.DAT" );

	// 반복자
	ostream_iterator ositer( outfile, " " );

	// list를 파일에 써넣음
	copy( iList.begin(), iList.end(), ositer );
}

//---------------------------------------------------------------------------
- istream_iterator 데이터의 시작위치는 cin_iter이며 끝은 무인수 생성자이다. 기본 생성자는 언제나 스트림 끝을 나타내는 istream_iterator를 만든다. (입력할때 스트림 끝값을 생성하려면 다 입력한 후 Ctrl + Z)
//---------------------------------------------------------------------------
// 작성일 : 2002.08.28
// 제  목 : istream_iterator cin 입력
// 작성자 : 남병철
//---------------------------------------------------------------------------

#include 
#include 
#include 

//---------------------------------------------------------------------------

void main()
{
	// 초기화되지 않은 list
	list fList( 5 );

	cout << "\nEnter 5 floating-point numbers";
	cout << "\n(Type [Ctrl] [z] to terminate) : ";

	// istream 반복자
	istream_iterator cin_iter( cin );
	istream_iterator end_of_stream;

	// cin에서 fList로 복사
	copy( cin_iter, end_of_stream, fList.begin() );

	cout << endl; // ostream_iterator로 fList를 화면 출력
	ostream_iterator ositer( cout, "--" );
	copy( fList.begin(), fList.end(), ositer );
}

//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// 작성일 : 2002.08.28
// 제  목 : istream_iterator file 입력
// 작성자 : 남병철
//---------------------------------------------------------------------------

#include 
#include 
#include 

//---------------------------------------------------------------------------

void main()
{
	list iList;
	ifstream infile( "ITER.DAT" );	// 입력 파일 객체 생성(ITER.DAT는 미리 존재해야함)

	// 대상 : 파일
	istream_iterator file_iter( infile );
	// 파일의 끝
	istream_iterator end_of_stream;

	copy( file_iter, end_of_stream, back_inserter( iList ) );

	cout << endl;
	ostream_iterator ositer( cout, "--" );
	copy( iList.begin(), iList.end(), ositer );
	cout << endl;
}

//---------------------------------------------------------------------------
(6) 연관성 컨테이너 map은 키와 값을 쌍으로 저장한다. 키는 정렬된 순서로 배열되며, 키를 사용하여 원소를 찾고 원소에 의해 값에 접근한다. set는 키만 저장하고 값은 없다. map과 set은 모두 각 키의 한 예만 저장할 수 있다. multi-set, multi-map은 같은 키에 여러 값을 가질 수 있다. 결국 연관성 컨테이너에는 set, multi-set, map, multi-map이 존재한다.
//---------------------------------------------------------------------------
// 작성일 : 2002.09.01
// 제  목 : set
// 작성자 : 남병철
//---------------------------------------------------------------------------

#include 
#include 
#include 

//---------------------------------------------------------------------------

void main()
{
	string names[] = { "Juanita", "Robert", "Mary", "Amanda", "Marie" };

	// set을 배열로 초기화
	set > nameSet( names, names+5 );

	// set에대한 반복자
	set >::iterator iter;

	nameSet.insert( "Yvette" );
	nameSet.insert( "Larry" );
	nameSet.insert( "Robert" );
	nameSet.insert( "Barry" );
	nameSet.erase( "Mary" );

	cout << "\nSize = " << nameSet.size() << endl;
	iter = nameSet.begin();
	while( iter != nameSet.end() )
		cout << *iter++ << '\n';

	string searchName;
	cout << "\nEnter name to search for : ";
	cin >> searchName;

	iter = nameSet.find( searchName );
	if( iter == nameSet.end() )
		cout << "The name " << searchName << " is NOT in the set.";
	else
		cout << "The name " << *iter << " IS in the set.";
}

//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// 작성일 : 2002.09.01
// 제  목 : set 안에서 범위를 시험
// 작성자 : 남병철
//---------------------------------------------------------------------------

#include 
#include 
#include 

//---------------------------------------------------------------------------

void main()
{
	set< string, less > organic;

	set< string, less >::iterator iter;

	organic.insert( "Curine" );
	organic.insert( "Xanthine" );
	organic.insert( "Curarine" );
	organic.insert( "Melamine" );
	organic.insert( "Cyanimide" );
	organic.insert( "Phenol" );
	organic.insert( "Aphrodine" );
	organic.insert( "Imidazole" );
	organic.insert( "Cinchonine" );
	organic.insert( "Palmitamide" );
	organic.insert( "Cyanimide" );

	iter = organic.begin();
	while( iter != organic.end() )
		cout << *iter++ << '\n';

	// 범위 지정
	string lower, upper;
	cout << "\nEnter range (example C Czz) : ";
	cin >> lower >> upper;
	iter = organic.lower_bound( lower );
	while( iter != organic.upper_bound( upper ) )
		cout << *iter++ << '\n';
}

//---------------------------------------------------------------------------
map 컨테이너의 데이터형은 아래처럼 리스팅에 자주 작성하기에는 긴편이다. map< string, int, less > mapStates; 이럴 경우 typedef으로 정의하여 간단히 사용할 수 있다. 또한 [] 연산자를 사용하면 map에 입력 및 찾기를 수행할 수있다.
//---------------------------------------------------------------------------
// 작성일 : 2002.09.01
// 제  목 : 도시별 인구수를 나타내는 map
// 작성자 : 남병철
//---------------------------------------------------------------------------

#include 
#include 
#include 

//---------------------------------------------------------------------------

int main()
{
	string name;
	int pop;

	string states[] = { "Wyoming", "Colorado", "Nevada", "Montana", "Arizona", "Idaho" };
	int pops[] = { 470, 2890, 800, 787, 2718, 944 };

	map< string, int, less > mapStates;
	map< string, int, less >::iterator iter;

	for( int j = 0; j < 6; j++ ) {
		name = states[j];
		pop = pops[j];
		mapStates[name] = pop;
	}
	cout << "Enter state : ";
	cin >> name;
	pop = mapStates[name];
	cout << "Population : " << pop << ",000\n";

	cout << endl;
	for( iter = mapStates.begin(); iter != mapStates.end(); iter++ )
		cout << (*iter).first << ' ' << (*iter).second << ",000\n";
	return 0;
}

//---------------------------------------------------------------------------
* Storing User-Defined Objects STL의 가장 큰 장점은 자신이 작성한 class를 저장하고 가공할 수 있다. 이름, 전화번호등의 개인정보를 기록하는 class를 만든후 multiset을 이용하여 전화번호부를 만들어 보자.
//---------------------------------------------------------------------------
// 작성일 : 2002.09.01
// 제  목 : multiset을 이용한 전화번호부
// 작성자 : 남병철
//---------------------------------------------------------------------------

#include 
#include 
#include 

//---------------------------------------------------------------------------

class person
{
	private:
		string lastName;
		string firstName;
		long phoneNumber;

	public:
		person() : lastName( "blank" ), firstName( "blank" ), phoneNumber( 0 ) {}

		person( string lana, string fina, long pho ) : lastName( lana ), firstName( fina ), phoneNumber( pho ) {}

		friend bool operator<( const person&, const person& );
		friend bool operator==(const person&, const person& );

		// display person's data
		void display() const {
			cout << endl << lastName << ",\t" << firstName << "\t\tPhone : " << phoneNumber;
		}
};

//---------------------------------------------------------------------------
// person 객체에 맞게 STL이 처리하도록 overloading 됨

// STL내부에서 person객체를 정렬하는데 사용
bool operator<( const person& p1, const person& p2 ) {
	if( p1.lastName == p2.lastName )
		return ( p1.firstName < p2.firstName ) ? true : false;
	return ( p1.lastName < p2.lastName ) ? true : false;
}

// STL내부에서 person객체를 비교하는데 사용
bool operator==( const person& p1, const person& p2 ) {
	return ( p1.lastName == p2.lastName &&
			 p1.firstName == p2.firstName ) ? true : false;
}

//---------------------------------------------------------------------------

int main()
{
	person pers1( "Deauville", "William", 8435150 );
	person pers2( "McDonald", "Stacey", 3327563 );
	person pers3( "Bartoski", "Peter", 6946473 );
	person pers4( "KuangThu", "Bruce", 4157300 );
	person pers5( "Wellington", "John", 9207404 );
	person pers6( "McDonald", "Amanda", 8435150 );
	person pers7( "Fredericks", "Roger", 7049982 );
	person pers8( "McDonald", "Stacey", 7764987 );

	// multiset of persons
	multiset< person, less > persSet;

	// iterator to a multiset of persons
	multiset< person, less >::iterator iter;

	// put persons in multiset
	persSet.insert( pers1 );
	persSet.insert( pers2 );
	persSet.insert( pers3 );
	persSet.insert( pers4 );
	persSet.insert( pers5 );
	persSet.insert( pers6 );
	persSet.insert( pers7 );
	persSet.insert( pers8 );

	cout << "\nNumber of entries = " << persSet.size();

	// display contents of multiset
	iter = persSet.begin();
	while( iter != persSet.end() )
		(*iter++).display();

	// get last and first name
	string searchLastName, searchFirstName;
	cout << "\n\nEnter last name of person to search for : ";
	cin >> searchLastName;
	cout << "Enter first name : ";
	cin >> searchFirstName;

	// create person with this name
	person searchPerson( searchLastName, searchFirstName, 0 );

	// get count of such persons
	int cntPersons = persSet.count( searchPerson );
	cout << "Number of persons with this name = " << cntPersons;

	// display all matches
	iter = persSet.lower_bound( searchPerson );
	while( iter != persSet.upper_bound( searchPerson ) )
		(*iter++).display();

	cout << endl;
	
	return 0;
}

//---------------------------------------------------------------------------
* list에 사용자 정의객체 넣어 사용하기 map이나 set이 아니므로 이름으로 찾기에서 lower_bound()/upper_bound()를 사용할 수 없다. 또한 사용자 정의객체를 list에 넣어 사용할때는 4개의 연산자를 오버로딩해야 한다. ==, !=, <, > 물론 어떤 알고리즘을 사용하느냐에따라 4개 모두 사용하느냐 아니냐가 달려있다.
    
//---------------------------------------------------------------------------
// 작성일 : 2002.09.02
// 제  목 : uses a list to hold person objects
// 작성자 : 남병철
//---------------------------------------------------------------------------

#include 
#include 
#include 
#include 

//---------------------------------------------------------------------------

class person
{
	private:
		string lastName;
		string firstName;
		long phoneNumber;

	public:
		person() : 
			lastName( "blank" ), firstName( "blank" ), phoneNumber( 0L ) 
			{}

		person( string lana, string fina, long pho ) : 
			lastName( lana ), firstName( fina ), phoneNumber( pho ) 
			{}

		friend bool operator<( const person&, const person& );
		friend bool operator==( const person&, const person& );
		friend bool operator!=( const person&, const person& );
		friend bool operator>( const person&, const person& );

		// display person's data
		void display() const {
			cout << endl << lastName << ",\t" << firstName << "\t\tPhone : " << phoneNumber;
		}

		// return phone number
		long get_phone() const {
			return phoneNumber;
		}
};

//---------------------------------------------------------------------------
// person 객체에 맞게 STL이 처리하도록 overloading 됨

bool operator==( const person& p1, const person& p2 ) {
	return ( p1.lastName == p2.lastName &&
			 p1.firstName == p2.firstName ) ? true : false;
}

bool operator<( const person& p1, const person& p2 ) {
	if( p1.lastName == p2.lastName )
		return ( p1.firstName < p2.firstName ) ? true : false;
	return ( p1.lastName < p2.lastName ) ? true : false;
}

bool operator!=( const person& p1, const person& p2 ) {
	return !( p1 == p2 );
}

bool operator>( const person& p1, const person& p2 ) {
	return !( p1 < p2 ) && !( p1 == p2 );
}

//---------------------------------------------------------------------------

int main()
{

	list persList;
	
	list::iterator iter1;

	persList.push_back( person( "Deauville", "William", 8435150 ) );
	persList.push_back( person( "McDonald", "Stacey", 3327563 ) );
	persList.push_back( person( "Bartoski", "Peter", 6946473 ) );
	persList.push_back( person( "KuangThu", "Bruce", 4157300 ) );
	persList.push_back( person( "Wellington", "John", 9207404 ) );
	persList.push_back( person( "McDonald", "Amanda", 8435150 ) );
	persList.push_back( person( "Fredericks", "Roger", 7049982 ) );
	persList.push_back( person( "McDonald", "Stacey", 7764987 ) );

	cout << "\nNumber of entries = " << persList.size();

	// display contents of list
	iter1 = persList.begin();
	while( iter1 != persList.end() )
		(*iter1++).display();

	// find person or person with specified name ( last and first )
	string searchLastName, searchFirstName;
	cout << "\n\nEnter last name of person to search for : ";
	cin >> searchLastName;
	cout << "Enter first name : ";
	cin >> searchFirstName;

	// make a person with that name
	person searchPerson( searchLastName, searchFirstName, 0L );

	// search for first match of names
	iter1 = find( persList.begin(), persList.end(), searchPerson );
	// find additional matches
	if( iter1 != persList.end() ) {
		cout << "Person(s) with that name is (are)";
		do {
			// display match
			(*iter1).display();
			++iter1;
			iter1 = find( iter1, persList.end(), searchPerson );
		} while ( iter1 != persList.end() );
	}
	else
		cout << "There is no person with that name.";

	// find person or persons with specified phone number
	cout << "\n\nEnter phone number (format 1234567) : ";
	long sNumber;
	cin >> sNumber;

	bool found_one = false;
	for( iter1=persList.begin(); iter1 != persList.end(); ++iter1 ) {
		if( sNumber == (*iter1).get_phone() ) {
			if( !found_one ) {
				cout << "Person(s) with that phone number is(are)";
				found_one = true;
			}
			(*iter1).display();
		}
	}

	if( !found_one )
		cout << "There is no person with that phone number";
	cout << endl;

	return 0;
}

//---------------------------------------------------------------------------
* Function Object 대부분의 주요한 C++ 연산자에 해당하는 함수객체가 존재한다.(function.h) 아래는 accumulate() 알고리즘 및 plus<>()함수객체를 보여준다. accumulate()는 직접 컨테이너의 각 원소들을 더하는것 보다 더 쉽고 간단하다. 엄청나게 복잡한 처리가 아니라면 이러한 코딩이 더 효과적이다. plus<>() 함수객체는 +연산자 오버로딩이 airtime Class를 위해 필요하다.
//---------------------------------------------------------------------------
// 작성일 : 2002.09.03
// 제  목 : uses accumulate() algorithm and plus() function object
// 작성자 : 남병철
//---------------------------------------------------------------------------

#include 
#include 
#include 

//---------------------------------------------------------------------------

class airtime
{
	private:
		int hours;	// 0 to 23
		int minutes;// 0 to 59

	public:
		airtime() : 
			hours( 0 ), minutes( 0 ) {}
		airtime( int h, int m ) :
			hours( h ), minutes( m ) {}
		void display() const
		{ cout << hours << ':' << minutes; }

		// input from user
		void get()
		{
			char dummy;
			cout << "\nEnter airtime (format 12:59) : ";
			cin >> hours >> dummy >> minutes;
		}

		airtime operator + ( const airtime right ) const
		{
			int temph = hours + right.hours;
			int tempm = minutes + right.minutes;
			if( tempm >= 60 )
			{ temph++; tempm -= 60; }
			return airtime( temph, tempm );
		}

		bool operator == ( const airtime& at2 ) const
		{ return ( hours == at2.hours ) && ( minutes == at2.minutes ); }

		bool operator < ( const airtime& at2 ) const
		{ return ( hours < at2.hours ) || ( hours == at2.hours && minutes < at2.minutes ); }

		bool operator != ( const airtime& at2 ) const
		{ return !( *this == at2 ); }

		bool operator > ( const airtime& at2 ) const
		{ return !( *this < at2 ) && !( *this == at2 ); }
};

//---------------------------------------------------------------------------

int main()
{
	char answer;
	airtime temp, sum;
	list airlist;

	// get airtimes from user
	do {
		temp.get();
		airlist.push_back( temp );
		cout << "Enter another (y/n)? ";
		cin >> answer;
	} while ( answer != 'n' );

	sum = accumulate( airlist.begin(), airlist.end(), airtime( 0, 0 ), plus() );
	cout << "\nsum = ";
	sum.display();
	cout << endl;

	return 0;
}

//---------------------------------------------------------------------------
* Writing Your Own Function Objects 첫번째 결과 원본 리스트이고 포인터 자체가 비교되 소트된 리스트가 뒤에 나온다. (포인터 자체를 정렬하는건 진정 우리가 원하는 소트가 아니므로 자주 쓰이지 않는다.) 마지막은 이름으로 소트된 정상적인 경우의 리스트가 나온다.
//---------------------------------------------------------------------------
// 작성일 : 2002.09.04
// 제  목 : uses accumulate() algorithm and plus() function object
// 작성자 : 남병철
//---------------------------------------------------------------------------

#include 
#include 
#include 
#include 

//---------------------------------------------------------------------------

class person
{
	private:
		string lastName;
		string firstName;
		long phoneNumber;

	public:
		person() :
			lastName( "blank" ), firstName( "blank" ), phoneNumber( 0L ) {}

		person( string lana, string fina, long pho ) :
			lastName( lana ), firstName( fina ), phoneNumber( pho ) {}

		friend bool operator < ( const person&, const person& );
		friend bool operator == ( const person&, const person& );

		// display person's data
		void display() const
		{
			cout << endl << lastName << ",\t" << firstName
				 << "\t\tPhone : " << phoneNumber;
		}

		// return phone number
		long get_phone() const
		{ return phoneNumber; }
};

//---------------------------------------------------------------------------

bool operator < ( const person& p1, const person& p2 )
{
	if( p1.lastName == p2.lastName )
		return ( p1.firstName < p2.firstName ) ? true : false;
	return ( p1.lastName < p2.lastName ) ? true : false;
}

//---------------------------------------------------------------------------

bool operator == ( const person& p1, const person& p2 )
{
	return ( p1.lastName == p2.lastName &&
			 p1.firstName == p2.firstName ) ? true : false;
}

//---------------------------------------------------------------------------
// function object

class comparePersons
{
	public:
		bool operator () ( const person* ptrP1,
						   const person* ptrP2 ) const
		{ return *ptrP1 < *ptrP2; }
};

//---------------------------------------------------------------------------
// function object

class displayPerson
{
	public:
		void operator () ( const person* ptrP ) const
		{ ptrP->display(); }
};

//---------------------------------------------------------------------------

int main()
{
	vector vectPtrsPers;

	person* ptrP1 = new person( "KuangThu", "Bruce", 4157300 );
	person* ptrP2 = new person( "Deauville", "William", 8435150 );
	person* ptrP3 = new person( "Wellington", "John", 9207404 );
	person* ptrP4 = new person( "Bartoski", "Peter", 6946473 );
	person* ptrP5 = new person( "Fredericks", "Roger", 7049982 );
	person* ptrP6 = new person( "McDonald", "Stacey", 7764987 );

	vectPtrsPers.push_back( ptrP1 );
	vectPtrsPers.push_back( ptrP2 );
	vectPtrsPers.push_back( ptrP3 );
	vectPtrsPers.push_back( ptrP4 );
	vectPtrsPers.push_back( ptrP5 );
	vectPtrsPers.push_back( ptrP6 );

	for_each( vectPtrsPers.begin(), vectPtrsPers.end(), displayPerson() );

	// 포인터를 정렬
	sort( vectPtrsPers.begin(), vectPtrsPers.end() );

	cout << "\n\nSorted pointers";
	for_each( vectPtrsPers.begin(), vectPtrsPers.end(), displayPerson() );

	sort( vectPtrsPers.begin(), vectPtrsPers.end(), comparePersons() );

	cout << "\n\nSorted persons";
	for_each( vectPtrsPers.begin(), vectPtrsPers.end(), displayPerson() );

	while( !vectPtrsPers.empty() )
	{
		delete vectPtrsPers.back();
		vectPtrsPers.pop_back();
	}
	cout << endl;
	return 0;
}

//---------------------------------------------------------------------------

+ -

관련 글 리스트
41 (12) STL ( Standard Template Library ) 남병철.레조 19650 2009/06/21
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.