[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; // 반복자 변경 불가능
}
```

# <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; 양방향 반복자는 불가능
}
```

```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;
}
```

```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;
}
```

```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;
}
```

```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의 원소를 뒤와 앞에 추가하는 예제이다.

```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를 하나의 템플릿 클래스로 제공하는 반복자의 공통된 인터페이스이다.
이들을 이용해서 임의의 반복자를 받는 알고리즘을 효율적으로 구현할 수 있다.


# <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 컨테이너

stack 컨테이너는 LIFO 방식의 컨테이너를 구현한 템플릿 클래스이다. stack 컨테이너에 설정된 기본 컨테이너는 deque 컨테이너이다.

다음은 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();
}
}
```

# <br>queue 컨테이너
queue 컨테이너는 FIFO 방식의 컨테이너를 구현한 템플릿 클래스이다. queue 컨테이너에 설정된 기본 컨테이너는 deque 컨테이너이다.


* 다음은 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이다.



* 다음은 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())하고 사용할 수 있다.

댓글
댓글 쓰기