[C++] 스터디 CPPALOM 11주차: 뇌를 자극하는 C++ STL Chap 10~12
파워 포인트 파일(.pptx)을 Markdown으로 변환하여 업로드하였음)
# <br>CPPALOM # <br>11주차 – 뇌를 자극하는 C++ STL Chap 10~12 한수빈 # <br>반복자의 종류 * 반복자는 포인터를 추상화한 클래스 객체이다. 다음 다섯 가지의 반복자가 있다: * 입력 반복자(input iterator): 전방향 읽기(istream) * 출력 반복자(output iterator): 전방향 쓰기(ostream) * 순방향 반복자(forward iterator): 전방향 읽기, 쓰기 * 양방향 반복자(bidirectional iterator): 양방향 읽기, 쓰기(list, set, multiset, map, multimap) * 임의 접근 반복자(random access iterator): 랜덤 읽기, 쓰기(vector, deque) # <br>X::iterator, X::const_iterator * X::iterator: * 정방향 반복자의 내장 형식이다. * 반복자가 가리키는 원소 읽기, 쓰기 가능. * X::const_iterator: * 정방향 반복자의 내장 형식이다. * 반복자가 가리키는 원소 읽기 가능. ```C++ 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); cout<<"v[iterator 읽기 가능] : "; for(vector<int>::iterator iter=v.begin(); iter != v.end(); ++iter) cout << *iter <<" "; cout << endl; cout<<"v[const iterator 읽기 가능] : "; for(vector<int>::const_iterator citer=v.begin(); citer != v.end(); ++citer) cout << *citer <<" "; cout << endl; vector<int>::iterator iter = v.begin(); vector<int>::const_iterator citer = v.begin(); *iter = 100; // 쓰기 가능! //*citer = 100; 쓰기 불가능! 에러- 상수 iterator로 가리키는 원소 수정 불가! } ``` ```C++ v[iterator 읽기 가능] : 10 20 30 40 50 v[const iterator 읽기 가능] : 10 20 30 40 5 ``` # <br>+ const iterator 반복자 자체가 const가 될 수도 있다. ```C++ void main() { vector<int> v; v.push_back(10); v.push_back(20); v.push_back(30); v.push_back(40); vector<int>::iterator iter = v.begin(); vector<int>::const_iterator citer = v.begin()+1; const vector<int>::iterator const_iter = v.begin()+2; const vector<int>::const_iterator const_citer = v.begin()+3; //iter는 모두 가능 *iter = 100; // 가리키는 원소 변경 가능 ++iter; // 반복자 변경 가능 //citer *citer = 200; // 가리키는 원소 변경 불가능 ++citer; // 반복자 변경 가능 //const_iter *const_iter = 300; // 가리키는 원소 변경 가능 ++const_iter; // 반복자 변경 불가능 //const_citer *const_citer = 400; // 가리키는 원소 변경 불가능 ++const_citer; // 반복자 변경 불가능 } ``` ![](img\week11_subin0.png) # <br>vector, list iterator vector의 경우 임의 접근 반복자이므로 추가적인 연산 기능을 제공한다. list는 앞뒤로 한 칸만 움직일 수 있다. ```C++ void main() { vector<int> v; v.push_back(10); v.push_back(20); v.push_back(30); list<int> lt; lt.push_back(10); lt.push_back(20); lt.push_back(30); vector<int>::iterator viter = v.begin(); list<int>::iterator liter = lt.begin(); cout <<"vector: "<< *viter <<endl; cout <<"list: "<< *liter << endl; cout <<"vector: "<< *++viter <<endl; cout <<"list: "<< *++liter << endl; cout <<"vector: "<< *--viter <<endl; cout <<"list: "<< *--liter << endl; viter += 2; // 임의 접근 반복자는 [], +=, -= +, -, <, >, <=, >=연산 가능 //liter += 2; 양방향 반복자는 불가능 } ``` ![](img\week11_subin1.png) ```C++ vector: 10 list: 10vector: 20 list: 20 vector: 10 list: 10 ``` # <br>reverse iterator * X::reverse_iterator: * 역방향 반복자의 내장 형식 * 반복자가 가리키는 원소 읽기, 쓰기 가능 * X::const_reverse_iterator: * 역방향 반복자의 내장 형식 * 반복자가 가리키는 원소 읽기 가능 ```C++ #include <iostream> #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); cout<<"v[iterator] : "; for(vector<int>::iterator iter= v.begin(); iter != v.end(); ++iter) cout << *iter <<" "; cout << endl; cout<<"v[reverse_iterator] : "; for(vector<int>::const_reverse_iterator riter=v.rbegin(); riter != v.rend(); ++riter) cout << *riter <<" "; cout << endl; } ``` ![](img\week11_subin2.png) ```C++ v[iterator] : 10 20 30 40 50 v[reverse_iterator] : 50 40 30 20 10 ``` # <br>반복자 어댑터 reverse_iterator<T> reverse_iterator<T>를 사용해 X::iterator와 X::const_iterator를 반대로 동작하도록 할 수 있다. ```C++ 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); //reverse_iterator 어댑터로 정방향 반복자를 역방향 반복자로 변환 reverse_iterator<vector<int>::iterator> rbiter(v.end()); reverse_iterator<vector<int>::iterator> reiter(v.begin()); cout<<"v [rbiter, reiter) : "; for( ; rbiter != reiter ; ++rbiter) cout << *rbiter <<" "; cout << endl; cout<<"v [rbegin(), rend()) : "; for(vector<int>::const_reverse_iterator riter=v.rbegin(); riter != v.rend(); ++riter) cout << *riter <<" "; cout << endl; } ``` ![](img\week11_subin3.png) ```C++ v [rbiter, reiter) : 50 40 30 20 10 v [rbegin(), rend()) : 50 40 30 20 10 ``` # <br>삽입 반복자 * 삽입 반복자는 순차열에 원소를 삽입(insert)할 수 있게 반복자를 변환하는 반복자 어댑터이다. * 모든 알고리즘은 기본적으로 덮어쓰기 모드로 동작한다. 삽입 반복자를 사용하면 알고리즘이 삽입 모드로 동작하게 할 수 있다. * inserter(): * insert_iterator 객체를 생성한다. insert_iterator 객체는 컨테이너의 insert() 멤버 함수를 호출해 삽입 모드로 동작하게 한다. * back_inserter(): * back_insert_iterator 객체를 생성한다. back_insert_iterator 객체는 컨테이너의 push_back() 멤버 함수를 호출해 뒤쪽에 삽입하도록 한다. * front_inserter(): * front_insert_iterator 객체를 생성한다. front_insert_iterator 객체는 컨테이너의 push_front() 멤버 함수를 호출해 앞쪽에 삽입하도록 한다. # <br>inserter() 다음은 inserter() 삽입 반복자 어댑터를 사용한 copy() 알고리즘 예제이다. copy() 알고리즘은 덮어쓰기 모드로 동작하므로 inserter()를 사용하지 않는다면 v2의 size가 0이므로 오류가 발생한다. ```C++ void main() { vector<int> v1; v1.push_back(10); v1.push_back(20); v1.push_back(30); v1.push_back(40); v1.push_back(50); vector<int> v2; // size: 0인 vector 생성 //copy(v1.begin(), v1.end(), v2.begin() ); //에러! //insert_iterator< vector<int> > insert(v2, v2.begin()); //copy(v1.begin(), v1.end(), insert ); 객체 생성 후 호출 copy(v1.begin(), v1.end(), inserter<vector<int> >(v2, v2.begin()) ); cout<<"v1 : "; for(vector<int>::iterator iter=v1.begin(); iter != v1.end(); ++iter) cout << *iter <<" "; cout << endl; cout<<"v2 : "; for(vector<int>::iterator iter=v2.begin(); iter != v2.end(); ++iter) cout << *iter <<" "; cout << endl; } ``` ![](img\week11_subin4.png) ```C++ vl : 10 20 30 40 50 v2 : 10 20 30 40 50 ``` # <br>back_inserter(), front_inserter() ```C++ 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); list<int> lt1; lt1.push_back(1); lt1.push_back(2); lt1.push_back(3); list<int> lt2; lt2.push_back(1); lt2.push_back(2); lt2.push_back(3); copy(v.begin(), v.end(), back_inserter<list<int> >(lt1) ); copy(v.begin(), v.end(), front_inserter<list<int> >(lt2) ); cout<<"v : "; for(vector<int>::iterator iter=v.begin(); iter != v.end(); ++iter) cout << *iter <<" "; cout << endl; cout<<"lt1 : "; for(list<int>::iterator iter=lt1.begin(); iter != lt1.end(); ++iter) cout << *iter <<" "; cout << endl; cout<<"lt2 : "; for(list<int>::iterator iter=lt2.begin(); iter != lt2.end(); ++iter) cout << *iter <<" "; cout << endl; } ``` 다음은 back_inserter와 front_inserter를 사용해 vector의 원소를 뒤와 앞에 추가하는 예제이다. ![](img\week11_subin5.png) ```C++ v : 10 20 30 40 50 ltl : 1 2 3 10 20 30 40 50 lt2 : 50 40 30 20 10 1 2 3 ``` # <br>입/출력 스트림 반복자 * 입/출력 스트림 반복자는 스트림과 연결된 반복자로 알고리즘이 스트림에 읽고 쓸 수 있게 하는 반복자 어댑터이다. * istream_iterator<T>: 입력 스트림과 연결된 반복자로 T 형식의 값을 스트림에서 읽을 수 있다. * ostream_iterator<T>: 출력 스트림과 연결된 반복자로 T 형식의 값을 스트림에 쓸 수 있다. # <br>ostream_iterator ```C++ 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); cout <<"v : "; copy(v.begin(), v.end(), ostream_iterator<int>(cout) ); cout <<endl; cout <<"v : "; copy(v.begin(), v.end(), ostream_iterator<int>(cout,", ") ); cout <<endl; list<int> lt; lt.push_back(100); lt.push_back(200); lt.push_back(300); cout <<"lt+v : "; transform(lt.begin(), lt.end(), v.begin(), ostream_iterator<int>(cout," "), plus<int>() ); cout <<endl; } ``` 다음은 출력 스트림 반복자를 사용해 copy(), transform() 알고리즘의 결과를 화면에 출력하는 예제이다. ```C++ v : 1020304050 v : 10, 20, 30, 40, 50, It+v : 110 220 330 ``` ```C++ #include <iostream> #include <algorithm> #include <vector> #include <iterator> using namespace std; void main() { vector<int> v; //표준 스트림에서 정수를 입력받아 v에 저장. copy(istream_iterator<int>(cin), istream_iterator<int>(), back_inserter<vector<int> >(v) ); cout <<"v : "; copy(v.begin(), v.end(), ostream_iterator<int>(cout," ") ); cout <<endl; // 정수를 스트림 끝(Ctrl-D)까지 입력 받아 화면에 출력합니다. //copy(istream_iterator<int>(cin), istream_iterator<int>(), ostream_iterator<int>(cout," ") ); } ``` * 다음은 입력 스트림 반복자를 사용한 copy() 알고리즘으로 표준 입력 스트림에서 입력받은 정수를 vector에 저장하거나 화면에 출력하는 예제이다. * 입력의 끝은 끝 스트림 반복자(end-of-stream iterator)를 사용하며 istream_iterator<T>()처럼 기본 생성자로 생성할 수 있다. * Ctrl-D는 표준 입력 스트림의 끝이다. ```C++ 10 20 30 40 50^D v : 10 20 30 40 50 ``` # <br>반복자 특성과 보조 함수 * 반복자는 반복자의 효율적인 사용을 위해 다섯 가지 반복자(입력, 출력, 순방향, 양방향, 임의 접근 반복자)로 분류한다. 이때 각 반복자는 자신만의 특징을 가지며 이 특징을 저장하는 템플릿 클래스를 가리켜 반복자 특성(iterator traits)라고 한다. * 반복자를 지원하는 두 함수 advance()와 distance() 함수로 임의 접근 반복자만이 가지고 있는 연산을 다른 반복자도 가능하게 지원한다. * advance(p, n): p 반복자를 p+=n의 위치로 이동시킨다. * n=distance(p1, p2): n은 p2-p1이다. # <br>advance() ```C++ void main() { vector<int> v; v.push_back(10); v.push_back(20); v.push_back(30); list<int> lt; lt.push_back(10); lt.push_back(20); lt.push_back(30); vector<int>::iterator viter(v.begin()); list<int>::iterator liter(lt.begin()); cout <<"viter: " <<*viter << endl; cout <<"liter: " <<*liter << endl; advance(viter, 2); // viter += 2 advance(liter, 2); cout <<"viter: " <<*viter << endl; cout <<"liter: " <<*liter << endl; advance(viter, -2); // viter -= 2 advance(liter, -2); cout <<"viter: " <<*viter << endl; cout <<"liter: " <<*liter << endl; } ``` 다음은 advance() 함수를 사용하여 vecto와 list의 반복자를 이동시키는 예제이다. viter는 임의 접근 반복자이므로 += 연산이나 -= 연산을 사용할 수 있지만 liter는 양방향 반복자이므로 distance() 함수를 사용해야 한다. ```C++ viter: 10 liter: 10 viter: 30 liter: 30 viter: 10 liter: 10 ``` # <br>distance() ```C++ #include <iostream> #include <vector> #include <list> #include <iterator> using namespace std; void main() { vector<int> v; v.push_back(10); v.push_back(20); v.push_back(30); list<int> lt; lt.push_back(10); lt.push_back(20); lt.push_back(30); cout <<"[v.begin(), v.end())의 원소 개수: " << distance(v.begin(), v.end()) << endl; //v.end()-v.begin() cout <<"[lt.begin(), lt.end())의 원소 개수: " << distance(lt.begin(), lt.end()) << endl; } ``` * list는 양방향 반복자를 제공하므로 lt.end()-lt.begin()은 불가능하다. * 대부분의 distance() 함수의 반환 형식은 unsigned int 혹은 int이지만 반복자마다 다르다. * 반복자 특성의 difference_type 형식이다. * iterator_traits<vector<int>::iterator>::difference_type n = distance(v.begin(), v.end()); ```C++ [v.begin() , v.end()) 의 원소 개수: 3 [lt.begin() , lt.end())의 원소 개수: 3 ``` # <br>반복자 특성 사용자 알고리즘을 구현할 때 STL 알고리즘처럼 일반화하면서도 반복자 종류의 특징에 따라 효율적인 동작을 하는 알고리즘을 구현하려면 STL이 제공하는 반복자 특성을 활용해야 한다. iterator_traits는 모든 반복자가 제공하는 다섯 가지 정보인 iterator_category, value_type, difference_type, pointer, reference를 하나의 템플릿 클래스로 제공하는 반복자의 공통된 인터페이스이다. 이들을 이용해서 임의의 반복자를 받는 알고리즘을 효율적으로 구현할 수 있다. ![](img\week11_subin6.png) ![](img\week11_subin7.png) # <br>iterator_traits 다음은 STL iterator_tag와 iterator_traits 클래스를 이용해 사용자 Advance() 보조 함수를 구현한 예제이다. Advance(viter, 2)는 viter가 임의 접근 반복자를 지원하므로 += 연산을 사용하며, Advance(liter, 2)는 liter가 양방향 반복자를 지원하므로 하나씩 ++ 연산을 수행한다. ```C++ // 입력 반복자, 출력 반복자 혹은 순방향 반복자에 맞는 버전 구현. // 양방향 반복자 Advance() 오버로딩 버전 template<typename Iter> void _Advance(Iter& iter, int n, bidirectional_iterator_tag category_tag) { for(int i = 0 ; i < n ; ++i) ++iter; std::cout <<"양방향 반복자 버전의 advance() ++iter 실행" << std::endl; } // 임의 접근 반복자 Advance() 오버로딩 버전 template<typename Iter> void _Advance(Iter& iter, int n, random_access_iterator_tag category_tag) { iter += n; std::cout <<"임의 접근 반복자 버전의 advance() iter += n 실행" << std::endl; } // Advance() 반복자 보조 함수 template<typename Iter> void Advance(Iter& iter, int n) { _Advance(iter, n, iterator_traits<Iter>::iterator_category() ); } ``` # <br>stack 컨테이너 ![](img\week11_subin8.png) stack 컨테이너는 LIFO 방식의 컨테이너를 구현한 템플릿 클래스이다. stack 컨테이너에 설정된 기본 컨테이너는 deque 컨테이너이다. ![](img\week11_subin9.png) 다음은 stack 컨테이너에 세 정수를 입력하고 출력하는 예제이다. ```C++ #include <iostream> #include <stack> using namespace std; void main( ) { stack<int> st; st.push(10); st.push(20); st.push(30); while( !st.empty() ) { cout << st.top() << endl; st.pop(); } } ``` ![](img\week11_subin10.png) # <br>queue 컨테이너 queue 컨테이너는 FIFO 방식의 컨테이너를 구현한 템플릿 클래스이다. queue 컨테이너에 설정된 기본 컨테이너는 deque 컨테이너이다. ![](img\week11_subin11.png) ![](img\week11_subin12.png) * 다음은 queue 컨테이너에 세 정수를 입력하고 출력하는 예제이다. * 기본 컨테이너는 list를 사용했다. ```C++ #include <iostream> #include <queue> #include <list> using namespace std; void main( ) { queue<int, list<int> > q; //리스트를 사용하는 queue 생성 q.push(10); q.push(20); q.push(30); while( !q.empty() ) { cout << q.front() << endl; q.pop(); } } ``` # <br>priority_queue 컨테이너 priority_queue 컨테이너는 우선순위 queue를 구현한 템플릿 클래스이다. priority_queue 컨테이너에 설정된 기본 컨테이너는 vector이다. ![](img\week11_subin13.png) ![](img\week11_subin14.png) ![](img\week11_subin15.png) * 다음은 priority_queue 컨테이너에 정수를 저장하고 우선순위에 따라 출력하는 예제이다. * pq1은 vector<int> 컨테이너를 사용하고 less 정렬 기준을 사용한 priority_queue 컨테이너이다. * pq2는 deque<int>를 사용하고 greater 정렬 기준을 사용한 priority_queue이다. ```C++ void main( ) { priority_queue<int> pq1; // 기본컨테이너 vector<int>, 기본정렬기준 less pq1.push(40); pq1.push(20); pq1.push(30); pq1.push(50); pq1.push(10); cout<<"priority_queue[less]:" <<endl; while( !pq1.empty() ) { cout << pq1.top() << endl; pq1.pop(); } cout <<"================" << endl; priority_queue<int, deque<int>, greater<int> > pq2; pq2.push(40); pq2.push(20); pq2.push(30); pq2.push(50); pq2.push(10); cout<<"priority_queue[greater]:" <<endl; while( !pq2.empty() ) { cout << pq2.top() << endl; pq2.pop(); } } ``` ```C++ priority_queue[less]: 50 40 30 20 10 ================ priority_queue[greater]: 10 20 30 40 50 ``` # <br>string * string은 vector 컨테이너와 비슷한 컨테이너이다. * 시퀀스 컨테이너이며 배열 기반 컨테이너의 범주에 속한다. * 표준 C++ 라이브러리는 문자와 관련한 두 컨테이너(string, wstring)을 제공한다. * string은 char 형식의 문자를 관리하기 위한 basic_string<char> 컨테이너의 typedef 형식이다. * wstring은 유니코드 문자(wchar_t)를 관리하기 위한 basic_string<wchar_t> 컨테이너의 typedef 형식이다. # <br>c_str() string 객체가 가지고 있는 문자열을 C-Style의 문자열로 변환하려면 c_str() 멤버 함수를 사용한다. 비슷한 함수로 data() 멤버 함수가 있으며, data() 멤버 함수는 ‘\0’ 문자를 포함하지 않는 문자의 배열을 반환한다. ```C++ #include <iostream> #include <string> using namespace std; void main( ) { string s("Hello!"); const char *sz; const char *buf; sz = s.c_str(); buf = s.data(); cout <<"'\\0'문자로 끝나는 문자열(C-style): " << sz << endl; cout <<"'\\0'문자 포함하지 않은 문자열 배열: "; for(int i=0 ; i < 6 ; ++i) cout << buf[i]; cout << endl; } ``` ```C++ ‘\0’문자로 끝나는 문자열(C-style): Hello! ‘\0’문자 포함하지 않은 문자열 배열: Hello! ``` # <br>find() * find(), rfind() 멤버 함수는 문자나 부분 문자열의 위치를 반환하는 함수이다. * 만약 문자가 없으면 string::npos 정의값을 반환한다. ```C++ void main( ) { const char *sz="\"Be careful in Uncle Randy's new car\", " "my sister told them. \"Wipe your feet before you get in it. " "Don't mess anything up. Don't get it dirty.\" " "I listened to her, and thought, " "as only a bachelor uncle can So I made things easy. " "while my sister was outlining the rules, " "I slowly and deliberately opened a can of soda, turned it over, " "and poured it on the cloth seats in the back of the convertible."; string t("Randy"); string s = sz; //s:string객체, sz:'\0'문자열, c:문자, off:시작위치, n:길이 cout << s << endl << endl; cout <<"s.find(c): "<< s.find('I') << endl; cout <<"s.find(c,off): "<< s.find('I', 250)<< endl; cout <<"s.find(sz): "<< s.find("poured it")<< endl; cout <<"s.find(sz,off): "<< s.find("poured it", 0)<< endl; cout <<"s.find(sz,off,n): "<< s.find("I listened to her",0,1)<< endl; cout <<"s.find(c): "<< s.find(t,0)<< endl << endl; string::size_type pos= s.find("Not found"); cout << (int)pos <<" : " << (int)string::npos << endl; pos = s.rfind('I'); if( string::npos != pos ) cout <<"s.rfind(c): " << pos << endl; } ``` ```C++ "Be careful in Uncle Randy’s new car", my sister told them. "Wipe your feet before you get in it. Don’t mess anything up. Don’t get it dirty." I listened to her, and thought, as only a bachelor uncle can So I made things easy, while my sister was outlining the rules, I slowly and deliberately opened a can of soda, turned it over, and poured it on the cloth seats in the back of the convertible. s.find(c) : 143 s.find(c,off) : 268 s.find(sz) : 336 s.find(sz,off) : 336 s.find(sz,off,n) : 143 s.find(c) : 21 -1 : -1 s.rfind(c) : 26 ``` # <br>replace() ```C++ void main( ) { string t("ABC"); string s1("Hello!"); … string s10("Hello!"); s1.replace(0, 3, "ABC"); s2.replace(0, 3, t); s3.replace(0, 3, "ABC", 2); s4.replace(0, 3, t, 0, 2); s5.replace(0, 3, 2, 'A'); s6.replace(s6.begin(), s6.begin()+3, "ABC"); s7.replace(s7.begin(), s7.begin()+3, t); s8.replace(s8.begin(), s8.begin()+3, "ABC", 2); s9.replace(s9.begin(), s9.begin()+3, 3, 'A'); s10.replace(s10.begin(), s10.end(), t.begin(), t.end()); //s:string객체,sz:'\0'문자열,c:문자,pos:위치,n:길이,ct:개수,iterb:시작반복자,itere:끝반복자 cout <<"s1.replace(pos, n, sz): "<< s1 << endl; cout <<"s1.replace(pos, n, s): "<< s2 << endl; cout <<"s1.replace(pos, n, sz, n2): "<< s3 << endl; cout <<"s1.replace(pos, n, s, pos2, n2): "<< s4 << endl; cout <<"s1.replace(pos, n, ct, c): "<< s5 << endl; cout <<"s1.replace(iterb, itere, sz): "<< s6 << endl; cout <<"s1.replace(iterb, itere, s): "<< s7 << endl; cout <<"s1.replace(iterb, itere, sz, ct): "<< s8 << endl; cout <<"s1.replace(iterb, itere, ct, c): "<< s9 << endl; cout <<"s1.replace(iterb, itere, iterb2, itere2): "<< s10 << endl; } ``` * replace() 멤버 함수를 사용하면 문자나 문자열을 교체할 수 있다. * 위치를 지정하는 버전과 반복자를 지정하는 버전이 있다. * s1.replace(pos, n, sz, n2)는 s1의 문자열 pos 위치로부터 n개의 문자열을 sz의 n2개의 문자열로 교체한다. ```C++ s1.replace(posz n, sz): ABClo! s1.replace(pos, n, s): ABClo! s1.replace(pos, n, sz, n2): ABlo! s1.replace(pos, n, s, pos2, n2): ABlo! s1.replace(pos, n, ct, c): AAlo! s1.replace(iterb, itere, sz): ABClo! s1.replace(iterb, itere, s): ABClo! s1.replace(iterb, itere, sz, ct): ABlo! s1.replace(iterb. itere, ctr c): AAAlo! s1.replace(iterb, itere, iterb2, itere2): ABC ``` # <br>substr() substr() 멤버 함수는 string 객체의 일부 문자열을 추출하고자 할 때 사용한다. ```C++ void main( ) { string t("Hello!"); string s1, s2, s3, s4, s5; s1 = t.substr(0); s2 = t.substr(0, string::npos); s3 = t.substr(0, 2); s4 = t.substr(2, 3); s5 = t.substr(2, string::npos); cout <<"substr(0)-0부터 끝까지: "<< s1 << endl; cout <<"substr(0, npos)-0부터 끝까지: "<< s2 << endl; cout <<"substr(0, 2)-0부터 2개: "<< s3 << endl; cout <<"substr(2, 3)-2부터 3개: "<< s4 << endl; cout <<"substr(2, npos)-2부터 끝까지: "<< s5 << endl; } ``` ```C++ substr (0)—0부터 끝까지: Hello! substr(0, npos) -0부터 끝까지: Hello! substr(0, 2)-0부터 2개: He substr(2, 3)-2부터 3개: llo substr(2, npos) -2부터 끝까지: llo! ``` # <br>getline() getline(in, s)는 스트림이 in으로부터 s로 문자열을 한 줄 입력받는다. cin.getline()처럼 세 번째 인자에 종료 문자를 지정할 수 있다. ```C++ #include <iostream> #include <string> using namespace std; void main( ) { string s1, s2; //cin >> buf와 같다. //cout << "두 문자열 입력:"<<endl; //cin >> s1 >> s2; //cout <<"s1: "<< s1 <<" s2: "<< s2 << endl; //cin.getline(buf)과 같다. cout << "두 문자열 입력(공백 문자 가능):"<<endl; getline(cin, s1); getline(cin, s2, '\n'); cout <<"s1: "<< s1 <<endl; cout <<"s2: "<< s2 << endl; } ``` ```C++ 두 문자열 입력 (공백 문자 가능) : um... mm.. woo.. always happy!!! s1: um... mm.. s2: woo.. always hap ``` # <br>string의 주요 멤버 함수 정리 * strin은 문자열 조작을 목적으로 만들어진 시퀀스 컨테이너이자 배열 기반 컨테이너입니다. * string은 임의 접근 반복자를 지원하며 컨테이너에 문자를 연속하게 저장한다. * vector처럼 메모리 공간을 예약(reserve())하고 사용할 수 있다. ![](img\week11_subin16.png)
댓글
댓글 쓰기