<개인공부>/[C++]

[C++] reverse 문자열을 거꾸로 하는 함수에 대해서

BlockDMask 2019. 11. 13. 04:04
반응형

안녕하세요. BlockDMask 입니다.

오늘은 C++ string 문자열을 거꾸로 돌려버리는 std::reverse 함수에 대해서 알아보도록 하겠습니다.

C++ string 관련해서 다른 함수들이 궁금하다면 C++ 문자열 총정리 [바로가기]


<목차>

0. std::reverse 함수 헤더파일

1. 문자열을 거꾸로 만드는 reverse 함수 선언과 정의 살펴보기

2. c++ 문자열 거꾸로 reverse 함수 예제

3. 문자열 뿐만 아니라 vector 등을 거꾸로 만들수 있는 reverse 함수의 진짜 사용법


0. std::reverse 함수 헤더파일


C++ : <algorithm>


1. 문자열을 거꾸로 만드는 reverse 함수 선언과 정의 살펴보기


함수 선언부와 정의부를 한번 따로 나누어서 살펴보겠습니다.


 reverse 함수 선언

template <class BidirectionalIterator>

void reverse(BidirectionalIterator first, BidirectionalIterator last)


template를 매개변수를 두개를 받게 됩니다.

간단하게 보면 "first로 들어온것부터 last 까지 요소들을 reverse 해라"라는 함수 같게 느껴집니다.


네 맞습니다. 


조금더 자세하게 살펴보면, first부터 last까지 포함한것이 아니라

[first, last) : first를 포함한 인덱스 부터 last 바로 전 인덱스까지의 요소들을 거꾸로 뒤집는 함수라고 말할 수 있습니다.


그리고 template로 선언된 매개변수 이름을 살펴보면 Bidirectional Iterator 라고 나와있습니다. Bidirectional는 생각하지 않아도, Iterator는 딱 느낌이 옵니다. 


네 그렇습니다. 

iterator를 타입을 매개변수로 본인이 reverse 하고 싶은 위치의 첫번째, 마지막을 reverse 함수에 넣으면 원본 데이터가 reverse 되는 함수 입니다. 


 std::reverse 함수 정의

template <class BidirectionalIterator>

void reverse(BidirectionalIterator first, BidirectionalIterator last)

{

while((first != last) && first != --last)

{

std::iter_swap(first++, last);

}

}


함수 내부를 살펴보면 while 반복문과 iter_swap 함수가 존재합니다.

while 반복문을 살펴보면, 바꾸려는 맨 처음과 맨끝이 같지 않은 상태이고, --last가 first와 같지 않은 상태일때 true가 됩니다.

iter_swap이라는 함수도 std 함수입니다. std::swap이라는 함수를 래핑해서 사용하는 함수인데요 우리가 아는 swap 함수에 한껍질 더 쌓아서 iterator를 스왑할 수 있도록 만든 함수 입니다.


그러면 감이좀 잡혔을까요?


한번 스탭을 따라가 볼까요?

"BlockDMask" 라는 문자열로 reverse(str.begin(), str.end()) 로 넣었다고 가정했을때.


1. first : B를 가리키게 되고, 

2. last : k의 다음 위치를 가리키는 상태가 됩니다. (str.end()는 맨 마지막 요소의 그 다음요소를 가리킵니다.)

3. while((first != last) && first != --last//while문을 들어가게 되면서 last는 -- 가 되어서 k를 가리키게 됩니다.

4. 그 후 std::iter_swap(first, last) -> std::iter_swap(B, k) 으로 함수가 들어가게 되고 k와 B의 요소는 바뀌게 됩니다.

5. std::iter_swap(first++  이었기 때문에 다음줄로 넘어가면서 first가 가리키는 것은 두번째 요소인 l 이 되고 (klockDMasB)

6. 다시 while문에서 --last로 인해서 last가 가리키는 요소는 맨 마지막에서 두번째요소인 s 를 가리키게 됩니다. (klockDMasB)


이런방식으로 쭉~쭉~쭉~쭉 (술이) 돌아가면서

last와 first가 만나는 시점에 while문이 false가 되며, reverse 함수가 끝나게 됩니다.


 reverse 함수 초간단 예제

string str = "BlockDMask";

cout << str << endl;            //"BlockDMask";

reverse(str.begin(), str.end());

cout << str << endl;            //"ksaMDkcolB";


2. c++ 문자열 거꾸로 reverse 함수 예제


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include<iostream>
#include<algorithm>    //reverse
#include<string>    //string
using namespace std;
 
int main(void)
{
    string str = "BlockDMask";
    cout << "=> reverse(str.begin(), str.end());" << endl << endl;
    cout << "Before : " << str << endl//"BlockDMask"
    
    reverse(str.begin(), str.end());
 
    cout << "After  : " << str << endl//"ksaMDkcolB"
    return 0;
}
cs


 결과


3. 문자열 뿐만 아니라 vector 등을 거꾸로 만들수 있는 reverse 함수의 진짜 사용법


함수의 정의를 다시 한번 봐 볼까요?

template <class BidirectionalIterator>

void reverse(BidirectionalIterator first, BidirectionalIterator last)


여기서 템플릿 타입으로 들어오는 T의 이름이 BidirectionalIterator 라고 작성되어있죠? 이것을 풀어 써보면

bidirectional iterator 즉 양방향 반복자를 말합니다.


양방향 반복자란?

양방향으로 이동이 가능한(=iterator가 ++, --가 가능한) 반복자를 말합니다.


결론적으로 말하면 reverse라는 함수는 양방향 반복자를 사용할 수 있는 컨테이너라면 무엇이든 reverse 함수를 사용할 수 있다는 것 입니다.


string 은 물론이고 vector(벡터), list(리스트)도 가능하게 됩니다.

벡터예제만 작성하겠습니다.


▼ 벡터 뒤집기 예제(vector reverse)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include<iostream>
#include<algorithm>    //reverse
#include<vector>
using namespace std;
 
void printVector(const vector<int>& v)
{
    for (auto val : v)
    {
        cout << val << ", ";
    }
    cout << endl;
}
 
int main(void)
{
    vector<int> v = { 12345678910 };
    cout << "=> reverse(v.begin(), v.end());" << endl << endl;
    cout << "Before : ";
    printVector(v);
    
    reverse(v.begin(), v.end());
 
    cout << "After : ";
    printVector(v);
    return 0;
}
cs


 결과


이렇게 vector도 reverse함수를 이용해서 이쁘게 잘 뒤집힌 것을 확인 할 수 있습니다.

오늘은 여기까지 작성하겠습니다.

감사합니다.

반응형