안녕하세요. 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 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; 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함수를 이용해서 이쁘게 잘 뒤집힌 것을 확인 할 수 있습니다.
오늘은 여기까지 작성하겠습니다.
감사합니다.
'<개인공부> > [C++]' 카테고리의 다른 글
[C++] minmax() 최대값 최소값을 동시에 구하는 함수에 대해서 (0) | 2019.11.25 |
---|---|
[C++] 최초값, 최대값 함수 min, max 에 대해서 (클래스, vector 사용법까지) (1) | 2019.11.22 |
[C++] map, set의 키를 클래스 구조체로 만드는 방법 (5) | 2019.11.20 |
[C++] 파일입출력(ofstream, ifstream)에 대해서. (2) | 2019.11.18 |
[C++] string 클래스, 문자열에 대해서 (총정리) (39) | 2019.03.29 |
[C++] range based for, 범위기반 for 반복문에 대해서. (1) | 2019.03.25 |
[C++] trunc 버림 함수에 대해서 (0) | 2019.03.19 |
[C++] round 반올림 함수에 대해서. (1) | 2019.03.19 |