{{ label!='' ? 'Label : ' : (q!='' ? '검색 : ' : '전체 게시글') }} {{ label }} {{ q }} {{ ('('+(pubs|date:'yyyy-MM')+')') }}

[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)

                       

댓글

이 블로그의 인기 게시물

[코딩의탑] 4층: 툰 쉐이딩

[코딩의탑] 3층: 바다 렌더링

[코딩의탑] 5층: 포탈(Portal), 더 나아가기