440 likes | 739 Views
표준 템플릿 라이브러리. Standard Template Library (C++ 로 배우는 객체지향 프로그래밍 , 7 장 ). 7.3. 표준 템플릿 라이브러리. STL(Standard Template Library) 표준 C++ 라이브러리의 일부 데이터 구조 + 연산 ( 알고리즘 ) 기본 구성 요소 컨테이너 (container) : 데이터 구조 vector, stack, queue, dequeue , list, set, map, … 알고리즘 (algorithm)
E N D
표준 템플릿 라이브러리 Standard Template Library (C++로 배우는 객체지향 프로그래밍,7장)
7.3.표준 템플릿 라이브러리 • STL(Standard Template Library) • 표준 C++ 라이브러리의 일부 • 데이터 구조 + 연산(알고리즘) • 기본 구성 요소 • 컨테이너(container) : 데이터 구조 • vector, stack, queue, dequeue, list, set, map, … • 알고리즘(algorithm) • 데이터 구조를 처리하기 위한 프로시저(함수) • container copy, sort, search, merge, permute,… • 반복자(iterator) • 한번에 하나씩 컨테이너 안의 원소를 액세스하기 위한 메커니즘 • 컨테이너를 임의의 방향으로(앞 뒤, 뒤 앞, …) 이동 가능 • for나 while 같은 반복 구조의 고급형 대안으로 제공
STL을 사용하는 이유 • STL 컨테이너 • 효율성 • 크기가 가변적 : C++ 배열과 달리 원소가 삽입되면, 크기가자동으로 늘어나고 원소가 삭제되면 자동으로 줄어듬 • 배열 오버플로 검사나 배열을 위한 기억장소를 동적으로 할당할 필요가 없음 • 프로그래밍이 용이하고 프로그램 오류가 적어지며 저장장치를 효율적으로 운용하는 효과 • 다양한 형태의 컨테이너(예: vector, associative array, set, stack, queue,…)를 제공 • 3가지 유형 : First-class containers, Adapters, Near containers • 컨테이너에 대한 시간 및 공간 복잡도(complexity)가 공표되어 있음
STL을 사용하는 이유 • STL 알고리즘 • 컨테이너를 위한 다양한 알고리즘 제공 • copy, sort, search, merge, permute, replace, reverse, … • 직관적이고 적용하기 쉬우며, 전역함수이므로 사용할 경우, 전체 코드의 readability 증가 • 내장형 반복구조 제공 • for_each • 융통성(flexiblity) • copy : 집합 집합, 집합 디스크 파일 간 복사 가능 vector< int > v; // fill up v with values for_each( v.begin(), v.end(), sq ); // 각 원소의 제곱
STL을 사용하는 이유 • STL 반복자 • STL 컨테이너와 알고리즘을 융통성과 효율성 있도록 만들어줌 • 포인터와 유사하게 동작 • first-class 컨테이너들의 개별 원소를 가리키는데 사용됨 • 내용참조 연산자(*)로 현재 가리키는 원소를 액세스 • ++연산자를 사용하여 iterator를 컨테이너의 다음 원소로 이동 • 프로그래머가STL 반복자를 포인터가 아닌 것처럼 사용할 수 있게 허용하는 고급 구조
STL을 사용하는 이유 • 예제 7.3.1. : STL 알고리즘의 융통성을 보여주는 예 • deque와 vector는 오름차순(default)으로 정렬됨 #include <vector> #include <deque> #include <algorithm> using namespace std; int main() { vector< int > v; deque< double > d; //v는 정수로 d는 부동소수점 수로 채움 sort( v.begin(), v.end() ); sort( d.begin(), d.end() ); //… } sort 알고리즘이 deque와 vector에 모두 동일한 방법으로 적용됨
STL을 사용하는 이유 • STL의 장점 • 효율성 • 융통성 • 사용 용이성 • 확장성 • 사용자가 새로운 컨테이너와 알고리즘을 추가할 수 있음 • STL 알고리즘은 내장형이나 사용자 정의형 컨테이너 상에서 사용 가능 • 사용자 정의형 알고리즘은 내장형이나 사용자 정의 컨테이너에 적용 가능 • STL 도구 집합 • 대규모이고 복잡한 응용 개발에 효과적
기본적인 컨테이너 • First-class STL 컨테이너(7가지) • 순차형(sequential)과 결합형(associative)
기본적인 컨테이너 • 순차형 컨테이너 : list, vector, deque • vector, deque • 원소가 위치에 의해, 인덱스를 사용하여 액세스 가능(배열과 유사) • list : 양방향 연결 리스트 • 원소 액세스를 위한 begin이나 end와 같은 멤버함수 제공 • 결합형컨테이너 : map, multimap, set, multiset • 컨테이너 내의 원소는 키로 액세스 예) m이 부동소수점 형태의 국민 총 생산량(GNP)을 저장하는 STL map이며 키로 국가 명을 사용한다면, float gnp = m[ “korea” ];
기본적인 순차형 컨테이너: vector, deque 및 list • 예제 7.3.2. #include <iostream> #include <vectors> using namespace std; int main() { int i; vector< int > nums; nums.insert( nums.begin(), -999 ); // -999 nums.insert( nums.begin(), 14 ); // 14 -999 nums.insert( nums.end(), 57 ); // 14 -999 57 for( i =0; i < nums.size(); i++) cout << nums[ i ] << endl; // 14 -999 57 cout << endl; nums.erase( nums.begin() ); // -999 57 nums.erase( nums.begin() ); // 57 for( i =0; i < nums.size(); i++) cout << nums[ i ] << endl; // 57 return 0; } 14 -999 57 57 • erase() : 벡터로부터 원소를 제거 • size() : 벡터의 현재 크기를 반환 • 연산자 []의 중복정의
기본적인 순차형 컨테이너: vector, deque 및 list • vector클래스 인스턴스 정의 • vector의 초기 크기를 명시하지 않는 경우 : 일반적 vector< double > d; • vector의 초기 크기를 명시하는 경우 : 모든 원소는 0으로 초기화 vector< double > d( 1000 ); • vector클래스 주요 멤버 함수 • begin() • 컨테이너가 not empty면 컨테이너의 첫 번째 원소를 가리키는 반복자 반환 • 컨테이너가 empty면 컨테이너의 끝 바로 다음을 가리키는 반복자 반환 • end() • 컨테이너의 끝 바로 다음을 가리키는 반복자 반환
기본적인 순차형 컨테이너: vector, deque 및 list • vector와 deque의 비교 • 그림 7.3.2 의 프로그램에 대해, #include <vector> #include <deque> vector< int > nums; deque< int > nums; 로 교체했을 때의, 출력은? • vector와 deque는 구현 상(특히 삽입과 삭제)에서 차이 • vector : 앞에 삽입하는 것이 끝에 삽입하는 것보다 비효율적 • deque : 삽입과 삭제가 앞쪽에서나 뒤쪽 어느 곳에서 일어나든 효율 면에서는 동일
기본적인 순차형 컨테이너: vector, deque 및 list • 예제 7.3.3. STL list컨테이너(그림 7.3.4 ) #include <iostream> #include <string> #include <list> using namespace std; void dump( list< string >& ); int main() { list< string > names; // 리스트에 4개의 원소를 삽입 names.insert( names.begin(), "Kamiko" ); // Kamiko names.insert( names.end(), "Andre" ); // Kamiko Andre names.insert( names.begin(), "Chengwen" );// ChengwenKamiko Andre names.insert( names.begin(), "Maria" ); dump( names ); // Maria ChengwenKamiko Andre names.reverse(); // 리스트를 역전 cout << endl; dump( names ); // Andre KamikoChengwen Maria return 0; }
(Cont’d) • 관련 반복자 type void dump( list< string >& l ) { list< const string >::const_iterator it; // 리스트 반복자 // 리스트를 표준 출력에 인쇄 it = l.begin(); // 반복자 초기화 while ( it != l.end() ) { // 반복자가 끝에 있는가 ? cout << *it << endl; it++; // 반복자 증가 } } list< int > vector< double > list< int >::iterator list< int >::const_iterator vector< double >::iterator vector< double >::const_iterator 컨테이너의 원소를 변경하지 않는다
vector, deque 및 list의 효율성 • 유사점 • insert, erase멤버 함수 등 • 차이점 • [] : vector, deque에서만 오버로딩 됨 • 연산의 효율성(time, storage) : 그림 7.3.5. vector deque list
기본적인 결합형 컨테이너:set, multiset 및 multimap • 2개 그룹 : sets, maps • set • 0개 이상의 중복되지 않는 원소 • Non-duplicated key들의 정렬되지 않은 집합 • 예) { 잡스, 게이츠, 엘리슨} • multiset : duplicated key를 허용하는 set • map • 0개 이상의 정렬되지 않은 쌍의 집합 • (non-duplicated key, key와 연관된 값) • 예) {(잡스, 애플), (게이츠, 마이크로소프트), (엘리슨, 오라클) } • multimap : duplicate key를 허용하는 map
기본적인 결합형 컨테이너:set, multiset 및 multimap • 예제 7.3.4. • 그림 7.3.6 : STL set 컨테이너 #include <iostream> #include <set> using namespace std; int main() { set< int > s; s.insert( -999 ); s.insert( 18 ); s.insert( 321 ); s.insert( -999 ); // duplicated! set< int >::const_iterator it; it = s.begin(); while ( it != s.end() ) cout << *it++ << endl; // -999 18 321 순 int key; cout << “Enter an integer: "; cin >> key; it = s.find( key ); if( it == s.end() ) // not found cout << key << " is not in set." << endl; else cout << key << " is in set." << endl; return 0; }
기본적인 결합형 컨테이너:set, multiset 및 multimap • 예제 7.3.5. STL map 컨테이너(그림 7.3.7 ) #include <iostream> #include <string> #include <map> using namespace std; int main() { map< string, int > m; m[ "zero" ] = 0; m[ "one" ] = 1; m[ "two" ] = 2; m[ "three"] = 3; m[ "four" ] = 4; m[ "five" ] = 5; m[ "six" ] = 6; m[ "seven"] = 7; m[ "eight"] = 8; m[ "nine" ] = 9; cout << m[ "three" ] << endl // 3 << m[ "five" ] << endl // 5 << m[ "seven" ] << endl; // 7 return 0; } value key
컨테이너 어댑터 • 컨테이너 어댑터(adaptor) • first-class 컨테이너가 아님 • 실제 데이터 구조에 대한 구현을 제공하지 않음 - 사용자가 원하는 데이터 구조를 선택 가능 • 반복자(iterators)를 지원하지 않음 • 공통 멤버 함수 • push – 데이터 구조에 하나의 원소를 삽입 • pop – 데이터 구조로부터 하나의 원소를 삭제 • 종류 : stack, queue, priority_queue • stack어댑터 : LIFO(List In First Out) 리스트 생성 • queue어댑터 : FIFO(First In First Out) 리스트 생성 • priority_queue어댑터 : 우선순위 순으로 원소를 삭제하는 큐 생성
컨테이너 어댑터 • 예제 7.3.6. : STL stack 어댑터(그림 7.3.8.) #include <iostream> #include <stack> #include <cctype> using namespace std; int main() { const string prompt = "Enter an algebraic expression: "; const char lParen = '('; const char rParen = ')'; stack< char > s; //*** STL stack; string buf; • 원소 : 디폴트는 deque stack< char > s; stack< char, deque< char > > s; • stack에 vector를 적용하려면, stack< char, vector< char > > s;
(Cont’d) //*** 완전한 괄호로 둘러싸인 산술식을 표준 입력에서 읽어들인다. cout<< prompt << endl; getline( cin, buf ); for ( int i = 0; i < buf.length(); i++) if( !isspace( buf[ i ] ) s.push( buf[ i ] ); cout << "Original expression: " << buf << endl; cout << "Expression in reverse: "; // 스택에서 문자를 꺼내 오른쪽 괄호와 왼쪽 괄호를 서로 바꾼다. while ( !s.empty() ) { char t = s.top(); // top 원소를 가져온다. s.pop(); // top 원소를 제거한다. if ( t == lParen ) t = rParen; else if ( t == rParen ) t = lParen; cout << t; } cout << endl; return 0; } • top() : top 원소를 삭제하지 않으면서 반환 • pop() : top 원소를 삭제하지만 반환 타입은 void
컨테이너 어댑터 • 예제 7.3.7. : STL queue 어댑터(그림 7.3.9) #include <iostream> #include <queue> using namespace std; int main() { queue< int > q; // == queue< int, deque< int > > q.push( 1 ); q.push( 3 ); q.push( 5 ); q.push( 7 ); q.push( 11 ); q.push( 13 ); // 큐가 빌 때까지 꺼내 인쇄: 출력은 1 3 5 7 11 13 while( !q.empty ) { cout << q.front() << endl; // 정수 반환 q.pop(); // void 반환 } return 0; } • 원소 : 디폴트는 deque • push() : 원소 삽입 • pop() : 원소 삭제 • front() : queue의 앞쪽 원소를 액세스
컨테이너 어댑터 • 예제 7.3.8. : STL priority_queue 어댑터(그림 7.3.10.) 8614 21890 3936 20054 3142 1191 *** Priority by value: 21890 20054 8614 3936 3142 1191 //… #include 부분 생략 int main() { const int howMany = 8; int i; priority_queue< int > nums; srand( time( 0 ) ); // seed rand for ( i = 0; i < howMany; i++ ) int next = rand(); cout << next << endl; nums.push( next ); } for ( i = 0; i < howMany; i++ ) { cout << nums.top() << endl; nums.pop(); // 원소 제거 } return 0; } • vector 또는 deque로구현 : 디폴트는 vector • push() : 원소 삽입 • pop() : 원소 삭제 • top() : 다음 원소를 삭제하지 않으면서 반환 원소가 정렬된 순서로 삽입되고, front에서 삭제됨 • 원소들은 우선 순위에 따라 삽입됨 • 가장 우선순위가 높은 원소가 먼저 삭제됨 • 힙정렬(heapsort)에 의해 정렬된 순서를 유지
기타 컨테이너 • string, bitset 클래스 • string 클래스 • bitset 클래스 • 01010101과 같은 이진 비트열(sequence or string of bits)
기타 컨테이너 • 예제 7.3.9. STL알고리즘에 의한 string 조작 프로그램 #include <iostream> #include <string> #include <algorithm> using namespace std; void printChar( char c ) { cout << c; } int main() { string s = "pele, the greatest ever"; cout << “s : " << s << endl; cout << "s in reverse: "; for_each( s.rbegin(), s.rend(), printChar ); cout << endl; char* where = find( s.begin(), s.end(), 'a' ); cout << 'a' is the " << where - s.begin() + 1 << "th char in: " << s << endl; • string 클래스 • 표준 STL 컨테이너의 begin과 end 메소드를 가짐 • STL 알고리즘을 사용하려면, #include <algorithm> 필요
(Cont’d) random_shuffle( s.begin(), s.end() ); cout << "s after a random shuffle: " << s << endl; where = find( s.begin(), s.end(), 'a' ); cout << "'a' is the " << where - s.begin() + 1 << "th char in: " << s << endl; sort( s.begin(), s.end() ); cout << "sorted in ascending order: " << s << endl; return 0; } s: pele, the greatest ever s in reverse: reve tsetaerg eht ,elep 'a' is the 14th char in: pele, the greatest ever s after a random shuffle: ,eptgeer etsht evlreae 'a' is the 21th char in: ,eptgeer etsht evlreae sorted in ascending order: ,aeeeeeeehlprrstttv
기타 컨테이너 • bitset클래스 • 이진수로 정수를 표현하는데 사용 • 변환생성자 • bitset( unsigned long n ); // n을 이진수로 나타낸 bitset을 생성 • 예 : bitset< 8 > bs( 9 ); • 멤버 함수 • 특정 비트를0이나 1로 만드는 멤버 함수 • 특정 비트 혹은 모든 비트를 한번에 역으로 하는 멤버 함수 • 특정 비트가 0으로 되어 있는지 또는 1로 되어 있는지 검사하는 멤버 함수 • 비트를 왼쪽이나 오른쪽으로 시프트하는멤버 함수 • and, or 및 exclusive-or 와 같은 표준이진 연산을 수행하는 멤버 함수 • bitset을 string 타입이나 unsigned long 타입 정수로 바꾸는 멤버 함수 #include <bitset> using namespace std; bitset< 8 > bs1; // 8 bits bitset< 128 > bs2; // 128 bits
기타 컨테이너 • 예제 7.3.10. • 그림 7.3.12. bitset 컨테이너 #include <iostream> #include <bitset> using namespace std; const featureCount = 8; const unsigned Framed = 1; // 00000001 const unsigned Bordered = 2; // 00000010 const unsigned StdMenu = 4; // 00000100 const unsigned ToolBar = 8; // 00001000 const unsigned StatusBar = 16;// 00010000 class Window { public: Window( const string& n, unsigned f ) { name = n; features = bitset< featureCount > ( f ); createWindow(); } Window( const char* n, unsigned f ) { name = n; features = bitset< featureCount > ( f ); createWindow(); }
(Cont’d) private: void createWindow() { cout << "\n*** Window features for " << name << " given bit mask " << features << ":" << endl; if ( features[ 0 ] ) // 1st bit set? (rightmost is 1st) cout << "\t" << "framed" << endl; if ( features[ 1 ] ) // 2nd bit set? cout << "\t" << "bordered" << endl; if ( features[ 2 ] ) // 3rd bit set? cout << "\t" << "with standard menu" << endl; if ( features[ 3 ] ) // 4th bit set? cout << "\t" << "with tool bar" << endl; if ( features[ 4 ] ) // 5th bit set? cout << "\t" << "with status bar" << endl; } string name; bitset< featureCount > features; }; • 개개의 비트가 인덱스를 통해 access되도록 중복정의 • 해당 비트가 1이면 true, 0이면 false를 반환
(Cont’d) • 출력 int main() { Window w1( "w1", Framed | ToolBar | StatusBar ); Window w2( "w2", ToolBar | Framed | StatusBar ); Window w3( "w3", Framed | StdMenu | StatusBar | ToolBar | Bordered ); return 0; } *** Window features for w1 given bit mask 00011001: framed with tool bar with status bar *** Window features for w2 given bit mask 00011001: framed with tool bar with status bar *** Window features for w3 given bit mask 00011111: framed bordered with standard menu with tool bar with status bar
알고리즘 • STL 알고리즘 • 종류 : 정렬 및 탐색, 수치 처리, 집합 연산, 복사 등 • 템플릿 함수로 구현(cf.STL 컨테이너 : 템플릿 클래스로 구현) • 예) STL reverse 알고리즘 프로토타입 • vector와 deque등에 똑같이 동작 • 컨테이너의 원소를 반복자를 사용하여 액세스하여 역순으로 놓음 template< class BidirectionalIterator > // 템플릿 헤더 void reverse( BidirectionalIterator it1, // 반복자1 BidirectionalIterator it2 ); // 반복자2
알고리즘 • 예제 7.3.11. STL 알고리즘 generate, replace_if, sort 및 for_each(그림 7.2.13) //… #include <algorithm> //*** for STL algorithm using namespace std; void dump( int i ) { cout << i << endl; } bool odd( int i ) { return i % 2 != 0; } bool comp( constint& i1, constint& i2 ) { return i1 > i2; } int main() { vector< int > v( 10 ); // 10개의 정수로 된 벡터 // 임의의 정수로 채운다. generate( v.begin(), v.end(), rand ); // 홀수는 0으로 대치한다. replace_if( v.begin(), v.end(), odd, 0 ); // 내림차순으로 정렬 sort( v.begin(), v.end(), comp ); for_each( v.begin(), v.end(), dump ); // 인쇄 return 0; }
(Cont’d) • generate • 범위 [first, last)를 함수 또는 함수 객체 g를 last - first번 호출해서 생성되는 값들로 채움 • 시간 복잡도 : 선형 • 예) generate( v.begin(), v.end(), rand ); #include <algorithm> template<class ForwardIt, class Generator> void generate(ForwardIt first, ForwardIt last, Generatorg);
(Cont’d) • replace_if • 범위 [first, last)에서 서술 p를 만족하는 모든 원소를 new로 대치 • 시간 복잡도 : 선형 • 예) replace_if( v.begin(), v.end(), odd, 0 ); #include <algorithm> template<class ForwardIt, class Pred, class T> void replace_if(ForwardIt first, ForwardIt last, Pred p, const T& new);
(Cont’d) • sort • 범위 [first, last) 내의 원소들을 정렬 • 정렬 방법 : • Version1 : 원소들을 비교하기 위해 <를 사용 • Version2 : 비교 서술 comp를 사용 • 평균 시간 복잡도 : n log n ( n : 정렬될 시퀀스의 길이) • 예) sort( v.begin(), v.end(), comp ); #include <algorithm> template<class RandomAccessIt> void sort(RandomAccessIt first, RandomAccessIt last); template<class RandomAccessIt, class Compare> void sort(RandomAccessIt first, RandomAccessIt last, Compare comp);
(Cont’d) • for_each • 반복자에 의해 그 내용이 참조되는 범위 [first, last) 안에 있는 각 원소에 함수 f를 한번씩 적용시킴 • 시간 복잡도 : 선형 • 예) for_each( v.begin(), v.end(), dump ); #include <algorithm> template<class InputIt, class Func> Func for_each(InputIt first, InputIt last, Func f);
알고리즘 • 예제 7.3.12. STL 알고리즘 nth_element, random_shuffle, copy(그림 7.3.14) main(){ const int len = 27; const int med = len / 2; char alph[] = "abcdefghijklmnopqrstuvwxyz{"; // 27 print( "\n\nOriginal array:\n", alph, len ); random_shuffle(alph, alph + len ); print( "\n\nAfter random-shuffle:\n", alph, len ); nth_element( alph, alph+med, alph+len ); print( "\n\nAfter nth elemnet:\n", alph, len); print( "\n\t < median: ", alph, med ); print( "\n\t median: ", alph + med, 1 ); print( "\n\t > median: ", alph + med + 1, len / 2 ); cout << endl; return 0; } void print( const char* msg, char a[], int len ) { cout << msg; copy( a, a + len, ostream_iterator< char >( cout, " " ) ); } 출력 스트림에 쓰여질 요소간의 분리자
(Cont’d) • 출력 예 Original array: a b c d e f g h i j k l m n o p q r s t u v w x y z { After random_shuffle: e t a r k m { l s y g q h o j x u z w p n b f d v c i After nth element: e i a c d f b h g j k l mno p q r s t u v { w z x y < median: e i a c d f b h g j k l m median: n > median: o p q r s t u v { w z x y
(Cont’d) • random_shuffle • 의사 난수를 발생시키는 rand와 같은 함수를 사용하여 무작위로 범위 [first, last) 내의 원소들을 재배열 • 결과로 생성되는 순열들은 uniform하게 분포됨 • Version 2 : 특정 난수 발생 함수 g를 매개 변수로 가짐 • 시간 복잡도 : 선형 • 예) random_shuffle( alph, alph + len ); #include <algorithm> template<class RandomAccessIt> void random_shuffle(RandomAccessIt first, RandomAccessIt last); template<class RandomAccessIt, class RandomnumberGen> void random_shuffle(RandomAccessIt first, RandomAccessIt last, RandomNumberGen& g);
(Cont’d) • nth_element • 전체 범위가 정렬되어 있다면, 정렬된 순서에 맞도록 위치 pos에 1개의 원소를 놓음 • any element to the left of pos any element to the right of pos • Version1 : <가 원소 비교를 위해 사용됨 • Version2 : comp가 원소 비교를 위해 사용됨 • 평균 시간 복잡도 : 선형 • 예) nth_element( alph, alph+med, alph+len ); #include <algorithm> template<class RandomAccessIt> void nth_element(RandomAccessIt first, RandomAccessIt pos, RandomAccessIt last); template<class RandomAccessIt, class Compare> void nth_element(RandomAccessIt first, RandomAccessIt pos, RandomAccessIt last, Compare comp);
(Cont’d) • copy • 다음 조건이 만족되도록 [first1, last1)을 [first2, last2)로 복사 last2 == first2 + ( last1 - first1 ) • 복사는 first1에서 last1-1까지 진행되고 last2를 반환 • 시간 복잡도 : 선형 • 예) copy( a, a + len, ostream_iterator< char >( cout, " " ) ); #include <algorithm> template< class InputIt, class OutputIt > OutputIt copy( InputIt first1, InputIt last1, OutputIt first2 );
알고리즘 • 예제 7.3.13. STL 출력 반복자(그림 7.3.15.) vector< int > fibs( 32 ); fibs[ 0 ] = fibs[ 1 ] = 1; // base case for ( int i = 2; i < 32; i++ ) fibs[ i ] = fibs[ i - 1 ] + fibs[ i - 2 ]; // 출력 스트림과 반복자 생성 ofstream outfile( "output.dat" ); ostream_iterator< int > outFileIt( outfile, " " ); ostream_iterator< int > stdOutIt( cout, "\n" ); // 출력 파일과 표준 출력에 복사 copy( fibs.begin(), fibs.end(), outFileIt ); copy( fibs.begin(), fibs.end(), stdOutIt );
(Cont’d) • ostream_iterator • ostream_iterator< int > outFileIt( outfile, “ “ ); • 디스크 파일과 연관된 반복자 • 출력을 구분하기 위해 빈칸 사용 • ostream_iterator< int > stdOutIt( cout, “\n” ); • 표준 출력과 연관된 반복자 • 출력을 구분하기 위해 newline 사용 • copy • copy( fibs.begin(), fibs.end(), outFileIt ); • copy( fibs.begin(), fibs.end(), stdOutIt ); • copy( fibs.rbegin(), fibs.rend(), stdOutIt ); • 역순으로 복사
참고 : C++ 파일처리 • 헤더 fstream을 포함 ifstream infile; // 파일을 읽고 쓰기 위한 변수 선언 ofstream outfile; infile.open( "income.in" ); //변수와 파일 연결 outfile.open( "tax.out" ); if ( infile >> income ) // 파일이 열려있다면 true // … infile.close(); // 파일 닫기 outfile.close();