이번에는 C++의 Pair 클래스에 대해 간단히 정리 해보려합니다. 클래스사용법, 함수 및 간단한 예제를 준비해봤습니다~

Pair 클래스란?

1. 두 객체를 하나의 객체로 취급 할 수 있게 묶어주는 클래스입니다.

2. STL에서 데이터 "쌍"을 표현할때 사용.

3. <utility> 헤더에 존재.

Pair 클래스 prototype

1. template <class T1, class T2> struct pair;

2. template <typename T1, typename T2> struct pair;
T1 : first T2 : second 로 구분합니다.

멤버 함수 및 간단한 사용법

1. pair<[type1], [type2]> p : 사용할 데이터 타입 1, 2를 넣고 그 타입의 pair 클래스인 p를 만듭니다.

2. p.first : p의 첫번째 인자를 반환해 줍니다.

3. p.second : p의 두번째 인자를 반환해 줍니다.
4. make_pair(변수1, 변수2) : 변수1과 변수2가 들어간 pair를 만들어줍니다.

5. operator로 (==, !=, <, >, <=, >=)가 정의 되어있어서, 사용이 가능합니다.

6. sort 알고리즘에 의해 정렬이 가능합니다.
(대소 비교 및 sort에의한 정렬에서 : 첫번째 인자 기준, 첫번째가 같으면 두번째인자로 판단)

int, string 인 경우 + 대소비교

#include<iostream>
#include<utility>
#include<string>
using namespace std;
 
void same(pair<int, string> a, pair<int, string> b){
    if(a == b){
        cout << "true" << endl;
    }else{
        cout << "false" << endl;
    }
}
void comp(pair<int, string> a, pair<int, string> b){
    if(a < b){
        cout << "true" << endl;
    }else{
        cout << "false" << endl;
    }
}
 
int main(void){
    pair<int, string> p1 = make_pair(1,"BlockDMask");    
    pair<int, string> p2 = make_pair(3,"Dok2");    
    pair<int, string> p3 = make_pair(1,"BlockDMask");    
 
    cout << "p1.first : " << p1.first << endl;
    cout << "p1.second : " << p1.second << endl;
    cout << endl;
    
    cout << "p1 == p2 ? ";
    same(p1, p2);
    cout << "p1 == p3 ? ";
    same(p1, p3);
    cout << endl;
    
    cout << "p1 < p2 ? ";
    comp(p1, p2);
    cout << "p1 < p3 ? ";
    comp(p1, p3);
    
    return 0;    
}
p1.first= 1
p1.second = BlockMask

p1 == p2 ? false
p1 == p3 ? true

p1 < p2 ? true
p1 < p3 ? false

vector 컨테이너의 타입으로 pair를 사용하는 경우. + 정렬(sort)

#include<iostream>
#include<utility>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
 
int main(void){
    vector<pair<int, string> > v;
    
    v.push_back(pair<int, string>(3, "Dok2"));    
    v.push_back(pair<int, string>(6, "DMask"));    
    v.push_back(pair<int, string>(1, "Tiger JK"));    
    v.push_back(pair<int, string>(4, "Block"));    
    v.push_back(pair<int, string>(2, "banana"));    
    v.push_back(pair<int, string>(2, "apple"));    
    
    cout << "=== After sort === " << endl;
    
    vector<pair<int, string> >::iterator iter;
    for(iter = v.begin(); iter != v.end(); iter++){
        cout << "[" << iter->first << "," << iter->second << "]" << endl;
    }
    
    cout << endl;
    sort(v.begin(), v.end());
    cout << "=== After sort === " << endl;
    
    for(iter = v.begin(); iter != v.end(); iter++){
        cout << "[" << iter->first << "," << iter->second << "]" << endl;
    }
 
    return 0;    
}

> 앞에 있는 first 인자부터 정렬이 되고, 같으면 뒤에 인자 (string의 경우 사전순)로 정렬됨을 banana와 apple을 보고 판단할 수 있습니다. for문 루프 문에서는 i=0~ v.size()로 설정하셔도 되지만 다른 방법도 있음을 알려드리기 위해서 iterator을 사용했습니다~~

 

출처 : https://blockdmask.tistory.com/64

 

'Language > C++' 카테고리의 다른 글

C++ - map, unordered_map  (0) 2020.06.27
C++ - 문자 및 문자열 찾기  (0) 2020.06.27
C++ - Stack, Queue  (0) 2020.06.23
C++ - Quick Sort (feat Algorithm qsort())  (0) 2020.06.23
C++ - 중복제거  (0) 2020.06.23

맵은 다른용어로 연관배열(php, javascript), 딕셔너리(python), 해시맵(java), js object(javascript)등으로 다양하게 불리운다. 사실 해시맵은 맵의 일종이라고 보시면 편하게 사용할 수 있습니다. 맵에 대해서 약간 설명해보면 맵은 인덱스를 문자열로 받는 배열이라고 생각하면 편하다. 일반배열이 숫자만을 인덱스 번호로 받는다면 맵은 문자열을 인덱스 번호로 받을 수 있다는 점입니다.

 

c++에서는 여러종류의 맵이 존재한다. 그 중에서 가장 유명한 맵은 map과 unordered_map이다. 이 둘은 각각 구현방법이 다르다. 그래서 사용하는 곳도 다르며 map은 balanced tree로 구현된다. 한국말로 하면 균형트리인데 균형트리중에서 red-black트리로 구현되있다. unordered_map은 hash table로 구현된다. 즉 해시맵인것입니다.

map

#include <map>
#include <iostream>

using namespace std;

int main() {
    map<string, int> m;

    /*insert*/cout<<"**********insert**********"<<endl;
    /*1*/m.insert(pair<string, int>("marin", 40));
    /*2*/m.insert(make_pair("scv", 60));
    /*3*/m["firebat"] = 50;

    /*iterate*/cout<<"**********iterate**********"<<endl;
    /*1*/map<string, int>::iterator it; // auto it = m.begin()도 가능
    for (it = m.begin(); it != m.end(); it++) {
        cout << it->first << " " << it->second << endl;
    }

    /*2*/for (pair<string, int> atom : m) {
        cout << atom.first << " " << atom.second << endl;
    }

    /*find*/cout<<"**********find**********"<<endl;
    /*1*/cout<<m.find("scv")->first<<" "<<m.find("scv")->second<<endl;
    /*2*/cout<<"scv"<<" "<<m["scv"]<<endl;


    /*erase*/cout<<"**********erase**********"<<endl;
    /*1*/m.erase("scv");
    /*2*/m.erase(m.find("marin"));
    for (pair<string, int> atom : m) {
        cout << atom.first << " " << atom.second << endl;
    }

    /*size*/cout<<"**********size**********"<<endl;
    cout<<m.size()<<endl;

    /*empty*/cout<<"**********empty**********"<<endl;
    cout<<m.empty()<<endl;

    return 0;
}
map<string, int> m;

선언은 위처럼 해준다. 왼쪽이 key값이고 오른쪽이 value이다. 내부적으로는 pair클래스를 적재하는 방식으로 사용합니다..

/*insert*/cout<<"**********insert**********"<<endl;
/*1*/m.insert(pair<string, int>("marin", 40));
/*2*/m.insert(make_pair("scv", 60));
/*3*/m["firebat"] = 50;

insert 방법은 3가지가 있습니다

먼저 1번째 방법은 pair를 각각 넣어주는 방식이다. 고대의 방식이며 현재는 이렇게 거의 사용하지 않는다. 뭐 사용할려면 사용하셔도...

 

2번과 3번은 iostream을 include해야만 사용할 수 있다. 이유는 모르겠다. 2번은 1번에서 업그레이드 된 방식이다. make_pair라는 함수를 사용하면 pair클래스가 리턴된다. 따라서 위처럼 사용하는 경우도 많다. 하지만.... 이제는 이 방법도 사용하지 않는다. 더 좋은 방식이 있기 때문이죠

 

3번은 이제 대부분 언어에서 쓰는 방식이다. 이 방식이 갓갓이니까 무조건 이 방식을 사용하라. 그낭 배열처럼 넣어주면된다. insert할 때 기존의 키에 값이 있으면 어떻게 되느냐? 값을 덮어쓴다. 애당초 그게 map의 존재이유 이니까 0_<.

/*iterate*/cout<<"**********iterate**********"<<endl;
/*1*/map<string, int>::iterator it; // auto it = m.begin()도 가능
for (it = m.begin(); it != m.end(); it++) {
    cout << it->first << " " << it->second << endl;
}

/*2*/for (pair<string, int> atom : m) {
    cout << atom.first << " " << atom.second << endl;
}

그럼 for문 반복 역시 두가지 방법이 있습니다. 배열과는 달리 무조건 iterator를 사용...했었어야 했지만 foreach가 나오면서 iterator를 호출해줄 필요는 없습니다. 1번 방식은 과거의 방식으로 iterator를 사용하는 방식입니다. 사실 이 방식은 지금도 사용할 가능성이 있어요!!

 

그건 배열이 foreach문으로 출력할 수 있어도 순회를 동적이게 해야할때 사용하듯이 map역시 마찬가지이다 라곤 하지만 거의 그렇게 쓸일은 없습니다. 2번은 foreach구문으로 사용해 주는 것이다. 현재 대부분은 이 방식을 사용합니다

/*find*/cout<<"**********find**********"<<endl;
/*1*/cout<<m.find("scv")->first<<" "<<m.find("scv")->second<<endl;
/*2*/cout<<"scv"<<" "<<m["scv"]<<endl;

원소를 참조하는 것역시 두가지 방법이 있습니다.(find)

1번 방식인 find를 사용하면 iterator가 나온다. 따라서 화살표연산으로 값을 지정해줘야한다. iterator가 포인터니까~

2번방식은 새로나온 방식이다. 1번방식 사용할 이유가.... 정말 단 한개도 없네요. 엄청 제한적인 상황에서 사용할수도 있지만 그 상황을 언급할 필요도 없을정도로 사용할 필요가 없습니다.

/*erase*/cout<<"**********erase**********"<<endl;
/*1*/m.erase("scv");
/*2*/m.erase(m.find("marin"));

원소를 지우는 방법 역시 두가지가 있다. 1번과 2번이 있는데 2번 같이 저렇게 사용하는 경우는 많지 않지만 iterator를 넣어서 사용하는 경우는 아직도 있습니다.

/*size*/cout<<"**********size**********"<<endl;
cout<<m.size()<<endl;

/*empty*/cout<<"**********empty**********"<<endl;
cout<<m.empty()<<endl;

마지막은 크기와 비어있는지 여부를 확인하는 함수입니다.

unordered_map

#include <unordered_map>
#include <iostream>

using namespace std;

int main() {
    unordered_map<string, int> m;

    /*insert*/cout<<"**********insert**********"<<endl;
    /*1*/m.insert(pair<string, int>("marin", 40));
    /*2*/m.insert(make_pair("scv", 60));
    /*3*/m["firebat"] = 50;
    /*2번과 3번은 iostream을 추가해줘야한다.*/

    /*iterate*/cout<<"**********iterate**********"<<endl;
    /*1*/unordered_map<string, int>::iterator it; // auto it = m.begin()도 가능
    for (it = m.begin(); it != m.end(); it++) {
        cout << it->first << " " << it->second << endl;
    }

    /*2*/for (pair<string, int> atom : m) {
        cout << atom.first << " " << atom.second << endl;
    }

    /*find*/cout<<"**********find**********"<<endl;
    /*1*/cout<<m.find("scv")->first<<" "<<m.find("scv")->second<<endl;
    /*2*/cout<<"scv"<<" "<<m["scv"]<<endl;


    /*erase*/cout<<"**********erase**********"<<endl;
    /*1*/m.erase("scv");
    /*2*/m.erase(m.find("marin"));
    for (pair<string, int> atom : m) {
        cout << atom.first << " " << atom.second << endl;
    }

    /*size*/cout<<"**********size**********"<<endl;
    cout<<m.size()<<endl;

    /*empty*/cout<<"**********empty**********"<<endl;
    cout<<m.empty()<<endl;

    return 0;
}

사용하는 방법은 map과 완전하게 같습니다~ 상황에 맞는걸 사용합시다!!!

 

map과 unordered_map은 사용하는 방법은 완전 동일하므로 뭘 쓰든 상관없으며 적은 데이터라면 큰 차이도 안나므로 뭘 쓰건 상관없습니다. 다시 말하지만 map은 균형트리인 red black tree로 구현되있고 unordered_map은  해시 테이블로 구현되어 있다는 것입니다.

 

어?? 그럼 일반적으로 unordered_map이 성능이 좋은거 아냐? 라고 묻는다면 당연히 yes입니다. 하지만 데이터가 많으면 많을수록 hash table의 성능은 리드미컬 하게 떨어진다.

 

그 이유야 뭐 간단한데 균형트리는 이론상 무조건 균형을 맞추게 되어 있다. 그러나 hash table은 값이 많아지면 비둘기집의 원리에 의해서 필연적으로 해쉬충돌이 일어나고 그러면 한 해시버킷에 충돌적재가 일어나서 결국에 성능은 떨어지게 된다는 것이다. 그래서 실제 벤치마크 테스트를 해보면 자료가 늘어나면 늘어날수록 성능은 unordered_map이 딸린다. 여러분도 잘 생각해서 고르면된다. 데이터가 작다면unordered_map이,크다면 map이 유리합니다.

 

멤버함수 종류

 

- m.begin();

- m.end();

- m.rbegin();

- m.rend();

- m.clear();

- m.count(k);

- m.empty();

- m.insert(k);     //k는 pair 객체입니다.

- m.insert(iter, k);

- m.erase(start, end);

- m.find(k);

- m2.swap(m1);

- m.upper_bound(k);

- m.lower_bound(k);

- m.equal_range(k);    

- m.value_comp();

- m.key_comp();

- m.size();

- m.max_size();

 

출처 : [c++][STL][map][unordered_map]C++에서 map(딕셔너리:dictionary, 연관배열:associate array,해시맵:hash map)사용하기(map과 unordered_map, 그리고 차이점)

'Language > C++' 카테고리의 다른 글

C++ - Pair  (0) 2020.06.27
C++ - 문자 및 문자열 찾기  (0) 2020.06.27
C++ - Stack, Queue  (0) 2020.06.23
C++ - Quick Sort (feat Algorithm qsort())  (0) 2020.06.23
C++ - 중복제거  (0) 2020.06.23

알고리즘 문제를 풀때 가끔씩 string 안에서 찾고자 하는 문자 및 문자열을 찾아 변형 한거나 지우는 경우를 종종 볼 수 있습니다. 이때 고민하지 않고 바로 적용할 수 있도록 방법을 알아보도록 합시다~.

 

먼저 해당 문자를 찾기 위해서는 가장 먼저 떠오르른 것이 find라는 함수 입니다. 그러면 먼저 find 함수에 대해 알아봅시다.

a.find("substring")

말 그대로 사용하시면 됩니다. 하지만 문제는 리턴값이다. 이를 별 생각없이 사용하면 문제가 생길 수 있습니다. 보통 find로 포함되는지 확인하고 싶다면 어떻게 써야하는가? 아마 대부분의 예제에서는 아래처럼 표현할 것이다.

#include <iostream>

using namespace std;

int main() {
    string a="hi hello";

    if(a.find("hi")>=0){
        cout<<a.find("hi")<<endl;
    }
    if(a.find("hello")>=0){
        cout<<a.find("hello")<<endl;
    }
    return 0;
}

대부분의 경우 find를 보면 >=0과 비교해서 참인지 알아낼 것이다.

0
3

왜냐하면 find함수의 리턴값은 바로 그 문자열의 위치(배열번호 위치, 즉 0번 부터 시작한다.)를 반환하기 때문이다.

그래서 >=0으로 표현하는 것이다.

 

여기까지는 괜찮다. 그런데 문제는 문자열에 없는 경우를 짜려고 할 경우이다. 이때 다른 언어에서는 -1을 반환하는 경우가 많기에 무의식적으로 음수라고 생각하는 경우가 있다. 그런데 cpp에서는 그렇지 않다.

#include <iostream>

using namespace std;

int main() {
    string a = "hi hello";

    if (a.find("sub") == string::npos) {
        cout << a.find("sub") << endl;
    }
    return 0;
}

문자열이 매칭되지 않는것은 쌩뚱맞게도 어떤 숫자와 매핑되어 있다. 그래서 위와 같이 코드를 작성해줘야 문자열이 포함되지 않는 경우인 것이다. 출력해보면 매우 큰수로 연결되있음을 알 수 있다.

18446744073709551615

int형은 그냥 벗어난 long long형 데이터이다. 그러므로 문자열을 찾을 때 신중히 사용하여야 한다.

 

그렇다면 또 다른 방법을 알아보자~

#include <iostream>
#include <cstring>
using namespace std;

int main() {
    string a = "hi hello";
    string b = "he";
    for(int i=0;i<a.size()-b.size();i++){
    	if(a.substr(i,b.size()).compare(b)==0){
        	cout<<i<<"\n";
            break;
        }
    }
    return 0;
}
3

"hi hello"에서 "he"를 찾으려고 할때 hi hello에서 찾으려고 하는 문자열의 사이즈만큼 이동을 해나가면서 찾는 방법입니다.

간단하게 설명하면~  hi와 he를 비교, i_  와 he를 비교, _h와 he를 비교, he와 he를 비교 해나가는 식으로 진행하면서 찾는 것입니다.

 

 

'Language > C++' 카테고리의 다른 글

C++ - Pair  (0) 2020.06.27
C++ - map, unordered_map  (0) 2020.06.27
C++ - Stack, Queue  (0) 2020.06.23
C++ - Quick Sort (feat Algorithm qsort())  (0) 2020.06.23
C++ - 중복제거  (0) 2020.06.23

C++에서 stack 사용법을 간단하게 알아보자!

스택 기본 함수

 

추가 및 삭제

1. push(element) : top에 원소를 추가

2. pop() : top에 있는 원소를 삭제

 

조회

1. top() : top(스택의 처음이 아닌 가장 끝)에 있는 원소를 반환

 

기타

1. empty() : 스택이 비어있으면 true 아니면 false를 반환

2. size() : 스택 사이즈를 반환

#include <iostream>
#include <stack>

using namespace std;

int main(){
	// 스택 생성
	stack<int> s;

	// push
	s.push(3);
	s.push(2);
	s.push(1);

	// top
	cout << "top element : " << s.top() << '\n';

	// pop
	s.pop(); // 1이 삭제
	s.pop(); // 2가 삭제

	// size
	cout << "stack size : " << s.size() << '\n';

	// empty
	cout << "Is it empty? : " << (s.empty() ? "Yes" : "No") << '\n';

	return 0;
}

큐 기본 함수

 

추가 및 삭제

1. push(element) : 큐에 원소를 추가(뒤에)

2. pop() : 큐에 있는 원소를 삭제(앞에)

 

조회

1. front() : 큐 제일 앞에 있는 원소를 반환

2. back() : 큐 제일 뒤에 있는 원소를 반환

 

기타

1. empty() : 큐가 비어있으면 true 아니면 false를 반환

2. size() : 큐 사이즈를 반환

#include <iostream>
#include <queue>

using namespace std;

int main(){
	// 큐 생성
	queue<int> q;

	// push
	q.push(1);
	q.push(2);
	q.push(3);
	q.push(4);
	q.push(5);
	q.push(6);

	// pop
	q.pop();
	q.pop();
	q.pop();

	// front
	cout << "front element : " << q.front() << '\n';

	// back
	cout << "back element : " << q.back() << '\n';

	// size
	cout << "queue size : " << q.size() << '\n';

	// empty
	cout << "Is it empty? : " << (q.empty() ? "Yes" : "No") << '\n';

	return 0;
}

출처: twpower.github.io/76-how-to-use-queue-in-cpp

'Language > C++' 카테고리의 다른 글

C++ - map, unordered_map  (0) 2020.06.27
C++ - 문자 및 문자열 찾기  (0) 2020.06.27
C++ - Quick Sort (feat Algorithm qsort())  (0) 2020.06.23
C++ - 중복제거  (0) 2020.06.23
C++ - 조합 및 순열  (0) 2020.06.23

이번에는 sort 보다 실행속도가 더 빠른 qsort에 대해 알아보도록 하겠습니다~.

C ++의 qsort () 함수는 Quicksort 알고리즘을 사용하여 지정된 배열을 오름차순으로 정렬합니다. 이 기능은<cstdlib> 헤더 파일에 정의되어 있습니다. qsort () 함수는 다음과 같이 지정된 배열을 정렬합니다. 

 

qsort() Prototype: qsort(array, num, type_size, compare_function)

void qsort (void* basesize_t numsize_t sizeint (*compare)(const void*,const void*));

Example : How qsort() function works?

#include <iostream>
#include <cstdlib>
using namespace std;

int compare(const void* a, const void* b)
{
	const int* x = (int*) a;
	const int* y = (int*) b;

	if (*x > *y)
		return 1;
	else if (*x < *y)
		return -1;

	return 0;
}

int main()
{
	const int num = 10;
	int arr[num] = {9,4,19,2,7,9,5,15,23,3};

	cout << "Before sorting" << endl;
	for (int i=0; i<num; i++)
		cout << arr[i] << " ";

	qsort(arr,num,sizeof(int),compare);
	cout << endl << endl;
	cout << "After sorting" << endl;

	for (int i=0; i<num; i++)
		cout << arr[i] << " ";

	return 0;
}

When you run the program, the output will be:

Before sorting
9 4 19 2 7 9 5 15 23 3
After sorting
2 3 4 5 7 9 9 15 19 23

출처: www.programiz.com/cpp-programming/library-function/cstdlib/qsort

'Language > C++' 카테고리의 다른 글

C++ - 문자 및 문자열 찾기  (0) 2020.06.27
C++ - Stack, Queue  (0) 2020.06.23
C++ - 중복제거  (0) 2020.06.23
C++ - 조합 및 순열  (0) 2020.06.23
C++ - String 클래스, 문자열 총정리  (0) 2020.06.19

벡터에서 중복 원소제거가 필요할 때가 있습니다. 그럴때 sort,unique,erase 의 기능을 적절히 활용하여 중복원소를 제거 할 수 있습니다.

먼저 백터하나를 만든뒤 데이터를 막넣습니다. (단 algorithm을 include 해주어야합니다 sort와 unique 사용을위해)

#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
using namespace std;

vector<int> s;

int main()
{
	s.push_back(1);
	s.push_back(2);
	s.push_back(1);
	s.push_back(3);
	s.push_back(2);
	s.push_back(1);
	s.push_back(2);
	
	printf("막넣은 백터s\n");
	for(int i=0;i<s.size();i  )
		cout<<s[i]<<"\t";
	printf("\n\n");
}
막넣은 백터s
1       2       1       3       2       1       2

그리고 바로 unique 를 해봅니다.

#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
using namespace std;

vector<int> s;

int main()
{
	s.push_back(1);
	s.push_back(2);
	s.push_back(1);
	s.push_back(3);
	s.push_back(2);
	s.push_back(1);
	s.push_back(2);
	
	printf("바로 unique(s.begin(),s.end());\n");
	unique(s.begin(),s.end());	
	for(int i=0;i<s.size();i  )
		cout<<s[i]<<"\t";
	printf("\n\n");
}
바로 unique(s.begin(),s.end());
1       2       1       3       2       1       2

바로 unique를 하게되면 아무런 변화가 없습니다. 이유는 unique는 연속된 중복 원소를 vector의 제일 뒷부분으로 쓰레기값으로 보내버립니다. 이를 확인하기위해 sort를 이용하여 vector를 정렬한뒤 unique를 해보겠습니다.

	printf("정렬 sort(s.begin(), s.end());\n");
	sort(s.begin(), s.end());
	for(int i=0;i<s.size();i  )
		cout<<s[i]<<"\t";
	printf("\n\n");
정렬 sort(s.begin(), s.end());
1       1       1       2       2       2       3
	printf("정렬후 unique(s.begin(),s.end());\n");
	unique(s.begin(),s.end());	
	for(int i=0;i<s.size();i  )
		cout<<s[i]<<"\t";
	printf("\n\n");
정렬후 unique(s.begin(),s.end());
1       2       3       2       2       2       3

C++ unique reference

  int myints[] = {10,20,20,20,30,30,20,20,10};           // 10 20 20 20 30 30 20 20 10
  std::vector<int> myvector (myints,myints 9);

  // using default comparison:
  std::vector<int>::iterator it;
  it = std::unique (myvector.begin(), myvector.end());   // 10 20 30 20 10 ?  ?  ?  ?

다음은 erase 로 뒤에붙은 쓰레기값을 제거해주면 백터의 중복원소를 제거하는데 성공합니다.

unique가 끝났으면 반환되는값은 vector의 쓰레기값의 첫번째 위치가 되는데요, 이때문에 바로 unique후 erase가 가능합니다.

	printf("백터.erase(unique(s.begin(),s.end()),s.end())\n");
	s.erase(unique(s.begin(),s.end()),s.end());
	for(int i=0;i<s.size();i  )
		cout<<s[i]<<"\t";
	printf("\n\n");
백터.erase(unique(s.begin(),s.end()),s.end())
1       2       3

이렇게 vector의 중복원소를 제거하는 방법에대해 알아보았습니다.

int형이아닌 문자도 중복제거가 가능합니다.

#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
using namespace std;

vector<string> s;

int main()
{
	s.push_back("a");
	s.push_back("b");
	s.push_back("a");
	s.push_back("c");
	s.push_back("b");
	s.push_back("a");
	s.push_back("b");
	
	printf("막넣은 백터s\n");
	for(int i=0;i<s.size();i  )
		cout<<s[i]<<"\t";
	printf("\n\n");
	
	printf("정렬 sort(s.begin(), s.end());\n");
	sort(s.begin(), s.end());
	for(int i=0;i<s.size();i  )
		cout<<s[i]<<"\t";
	printf("\n\n");

	printf("백터.erase(unique(s.begin(),s.end()),s.end())\n");
	s.erase(unique(s.begin(),s.end()),s.end());
	for(int i=0;i<s.size();i  )
		cout<<s[i]<<"\t";
	printf("\n\n");
}
막넣은 백터s
a       b       a       c       b       a       b
정렬 sort(s.begin(), s.end());
a       a       a       b       b       b       c
백터.erase(unique(s.begin(),s.end()),s.end())
a       b       c

출처: dpdpwl.tistory.com/39

 

 

C++에서는 next_permutation을 활용하여 순열과 조합을 만들수 있습니다. 그러면 직접 보면서 순열, 조합에 대해 알아봅시다~

먼저 순열에 대해 보도록 하겠습니다

 

중복이 있는 원소들의 경우

중복이 있는 원소의 경우 중복인 경우를 제외하고 순열을 만들어줍니다. 즉, 예를 들어서 0 1 1이 있다면 아래와 같은 경우만 순열을 출력해줍니다.

#include <stdio.h>
#include <vector>
#include <algorithm>
using namespace std;
int main (){
	vector<int> v;
	// 0 1 1 대입
	v.push_back(0);
	v.push_back(1);
	v.push_back(1);
	// 정렬
	sort(v.begin(), v.end());
	//순열
	do{
		// 출력
		for(int i=0; i<v.size(); i++){
			printf("%d ", v[i]);
		}
		printf("\n");
	}while(next_permutation(v.begin(), v.end()));

	return 0;
}
0 1 1
1 0 1
1 1 0

next_permutation을 이용해 조합(Combinataion) 구하기

원리: 전체 n개의 원소들 중에서 k개를 뽑는 조합(=nCk)을 구한다면 n개의 벡터 원소에 1을 k개 0을 나머지인 n-k개 집어넣어서 순열을 돌리고 1에 해당하는 인덱스만 가져오면 된다.

 

1부터 6까지의 수 중에서 4개를 뽑아서 조합을 만들어보자.

#include <stdio.h>
#include <vector>
#include <algorithm>

using namespace std;

int main (){
	// 1부터 6까지 담을 벡터
	vector<int> n;
    
	// 1부터 6까지 생성
	for(int i=0; i<6; i++){
		n.push_back(i+1);
	}
	// 0과1을 저장 할 벡터 생성
	vector<int> ind;
    
	// k=4, 4개를 뽑으니까
	int k = 4;
    
	// k개의 1 추가
	for(int i=0; i<k; i++){
		ind.push_back(1);
	}

	// 2개(6개-2개)의 0 추가
	for(int i=0; i<n.size()-k; i++){
		ind.push_back(0);
	}

	// 정렬
	sort(ind.begin(), ind.end());

	//순열
	do{
		// 출력
		for(int i=0; i<ind.size(); i++){
			if(ind[i] == 1){
				printf("%d ", n[i]);
			}
		}
		printf("\n");
	}while(next_permutation(ind.begin(), ind.end()));

	return 0;
}
3 4 5 6
2 4 5 6
2 3 5 6
...
1 2 3 6
1 2 3 5
1 2 3 4

 

출처: twpower.github.io/90-combination-by-using-next_permutation

BlockDMask님의 정리 자료를 학습 및 참고하고자 가지고 왔습니다.

오늘은 C++의 std::string 클래스(문자열)에 대해서 세세 하게 알아볼것 입니다.

문자열 관련 특정 함수 예제만 보실분들은 아래 예제들에서 사용한 멤버 함수들을 적어 두었으니 해당 예제로 바로 내려가시면 됩니다. 

 

<목차>

1. C++ string 클래스 헤더파일과 설명 그리고 생성하는 방법.

2. C++ string 클래스 멤버함수 거~의 대부분 정리 (꼼꼼하게 작성했습니다.)

-> at(), operator[], front(), back()

-> size(), length(), capacity(), resize(), shrink_to_fit(), reserve(), clear(), empty()

-> c_str(), substr(), replace(), compare(), copy(), find(), push_back(), pop_back()

-> begin(), end()

-> swap(), operator+

3. C++ string 클래스 예제1 (생성과 출력, 문자열 연결, push_back, pop_back)

3. C++ string 클래스 예제2 (size, capacity, length, clear)

4. C++ string 클래스 예제3 (substr, replace, swap)

5. C++ string 클래스 예제4 (find, operator[], at, front, back)

6. C++ string 클래스 예제5 (begin, end, copy, compare)

1. C++ string 클래스 헤더파일과 설명 그리고 string을 생성하는 여러가지 방법.

▼ string 클래스 헤더파일, 생성방법

헤더파일 : <string>

생성1     : string str("BlockDMask");

생성2     : string str1; str1 = "BlockDMask";

생성3     : string str2(str1);

(using namespace std; 를 추가해주어야 합니다.)

 

string 클래스는 말씀드린것 처럼 string을 다루는 클래스 입니다.

또한, C언어의 char*, char[] 문자열과 달리, 문자열끝에 '\0'이런게 들어있지 않습니다. 자 그럼 C++ string 에서는 어떤 편리한 기능이 있는지 살펴보러 가겠습니다.

 

2. C++ string 클래스 멤버함수 정리 (거의 대부분)

std::string 에는 문자열을 다루는 정말 여러 멤버 함수들이 존재합니다. 우리는 이 멤버함수들을 적절하게 사용하여 원하는 프로그램을 만들면 됩니다.

 

♣ 중요중요

string str1 = "BlockDMask"; 

string str2 = "BlogBlogBlogBlog"; 인 상태에서 시작하겠습니다.

하나의 멤버함수 내에서 예시들은 이어지게되고.

각 멤버 변수가 시작할때 str1, str2는 처음과 같이 초기화 되었다고 가정하겠습니다.

 

♣ string 인자 접근, access 관련

 str1.at(index)

함수 원형 : char& at (size_t index);

함수 설명 : index(=인덱스) 에는 숫자가 들어가게되고, 해당 위치(n)에 해당하는 문자를 반환합니다. index는 0부터 시작합니다. index가 string의 범위를 벗어나게 되면 예외를 뱉습니다.

 

함수 예시 : str1.at(0);    //"BlockDMask" -> 'B'를 리턴합니다.

 

 str1.operator[index]

함수 원형 : char& operator[](size_t index);

함수 설명 : C++ string은 일반 배열처럼 대괄호를 이용해서 string 인자에 접근할 수 있습니다. at과 다른점은 string의 index(인덱스)범위를 검사하지 않기 때문에 at 함수보다는 빠릅니다. 하지만 예외를 뱉어내지 않습니다. index는 0부터 시작합니다. index 번째 인자를 반환합니다.

함수 예시 : str1[1];    //"BlockDMask" -> 'l'를 리턴합니다.

 

 str1.front();

함수 원형 : char& front();

함수 설명 : C++11부터 가능합니다. string의 맨 앞 인자를 반환합니다.

함수 예시 : str1.front();    //"BlockDMask" -> 'B'를 리턴합니다.

 

 str1.back();

함수 원형 : char& back();

함수 설명 : C++11부터 가능합니다. string의 맨 뒤 인자를 반환합니다. 

  개인적으로 front는 모르겠지만 back은 참 좋은 멤버변수인것 같습니다. 우리가 string의 첫번째 인자를 가지려고 할때는 str1[0]을 인덱스로 집어 넣으면 되지만 끝부분은 대부분 다른 멤버변수에 저장을 해놓거나 잘 모르는 경우가 많습니다. 그렇기 때문에 back() 을 이용하면 편하게 맨 뒤 인자를 가지고 올 수 있습니다.

함수 예시 : str1.back();    //"BlockDMask" -> 'K'를 리턴합니다.

 

♣ string size 관련

▶ str1.size();

함수 원형 : size_t size() const;

함수 설명 : string의 사이즈를 반환합니다.

함수 예시 : str1.size();    // "BlockDMask" 이므로 10을 반환합니다.

 

 str1.length();

함수 원형 : size_t length() const;

함수 설명 : string의 길이를 반환합니다. size() 함수와 같다고 생각하면 됩니다.

함수 예시 : str1.length();    // "BlockDMask" 이므로 10을 반환합니다.

 

 str1.capacity();

함수 원형 : size_t capacity() const;

함수 설명 : string 객체에 할당된 메모리 크기(bytes)를 반환합니다. capacity는 vector의 capacity와 마찬가지로 스트링 길이가 증가할 수 있기 때문에, 메모리 할당을 size에 대비해서 여유롭게 합니다. size가 capacity를 넘게 될때 새롭게 더 큰 capacity(메모리)를 할당합니다.

 

함수 예시 : str1.capacity();    // "BlockDMask" 길이는 10인데 capacity는 15 입니다.

함수 예시 : str2.capacity();    // "BlogBlogBLogBlog" 길이는 16인데 capacity는 31 입니다.

 

15 -> 31 이런식으로 스트링의 capacity가 넘어가는 것을 알 수 있습니다.

길이가 10 인 스트링을 우리가 str1 += "a"  이런식으로 계속해서 길이를 늘리다가 16이 되는순간 기존의 capacity를 넘어가므로 더 큰 capacity를 할당하여서 스트링을 다루게 됩니다.

 

 str1.resize(n);

함수 원형 : void resize (size_t n);

함수 원형 : void resize (size_t n, char c);

함수 설명 : string을 n만큼의 크기로 만듭니다. 

  만약 그 크기가 원래 사이즈 보다 작다면, 남은 스트링을 버립니다. 

  만약 그 크기가 원래 사이즈 보다 크다면, 빈 공간으로 남은 공간을 채웁니다. 만약 c를 사용한다면 남은 공간을 c로 채울 수 있습니다.

함수 예시 : str1.resize(5)    // "BlockDMask" -> "Block" 이 됩니다. size는 5입니다.

함수 예시 : str1.resize(6)    // "Block" -> "Block " 가 됩니다. 빈칸이 있습니다. size는 6이 되었습니다.

함수 예시 : str1.resize(10, 'a') // "Block " -> "Block aaaa" 가 됩니다. 사이에 빈칸이 하나 있는거 보이시죠? q 추가했던 그것입니다.

 

 str1.shrink_to_fit();

함수 원형 : void shrink_to_fit();

함수 설명 : C++11 입니다. 이 함수는 스트링 길이에 비해 낭비되고 있는 capacity(메모리)를 줄이는 함수입니다. 

함수 예시 : str2.resize(4);    // "BlogBlogBlogBlog" -> "Blog" 가 됩니다. 아까 capacity에서 보자면 길이가 16짜리 string의 capacity는 31 이었습니다.

 

함수 예시 : str2.shrink_to_fit();    // "Blog" 처럼 길이가 4가 된 스트링의 capacity에 알맞게 str2의 capacity가 31에서 16으로 줄어들게 됩니다.

 

 str1.reserve(n);

함수 원형 : void reserve(size_t n = 0);

함수 설명 : 문자열을 넣기 전에 미리 "곧 n만큼의 크기의 스트링이 들어올거니까 그에 맞는 capacity를 할당해 달라"는 함수 입니다. 이건 보통 파일을 읽을 때 사용을 하는데요, 3000자 짜리 파일을 우리가 읽게 된다하면, 파일에 있는 글을 한자씩 가지고 오게되는데 이게 while문에서 eof를 이용해서 파일의 끝 까지 읽게 됩니다. 이런 경우에는 미리 메모리를 할당해서, capacity가 사이즈에 맞게 계속 늘어나는 행위를 덜하게해서 성능저하를 줄이게 하는 것 입니다.

 

만약에 reserve를 하지 않고 그냥 파일을 읽는다면 아마 이렇게 될 것 입니다. str += "글" 이렇게 계속 파일이 끝이 나올 때 까지 더해질 것이고, str의 길이가 16이 되면 새롭게 capacity를 늘리는 작업이 들어가서 비용이 들게되고, 또 str의 길이가 32가 되면 새롭게 capacity를 늘리는 작업이 들어가게 되고....... 계속 .... 계속.... 늘리는 작업을 하게 됩니다. 이런 비효율적인 작업을 하지 않게 하려고 미리 메모리 예약을 하는 것 입니다.

 

쉽게 말해서 노래방에 2인실을 갔는데, 2명이 더와서 4인실을 갔는데 또 여러명이 와서 8인실을 가고 이렇게 사람들이 이동하는 동안 우리는 노래를 못부르고 시간이 줄잖아요. 컴퓨터도 마찬가지 입니다 한번 할당해 놓은 메모리를 또 추가로 할당한다는 것은 그만큼 비용이 생기게 됩니다.

 

 str1.clear();

함수 원형 : void clear();

함수 설명 : 스트링에 들어있는 문자열을 지우는 함수입니다. 이때, size와 length는 0이 되고, capacity는 그대로 남게 됩니다.

함수 예시 : str1.clear();    //"BlockDMask" -> "" 이 됩니다. size와 lenth는 0이 되고, capacity는 15 그대로 입니다. (메모리 해제가 아닌 문자열 값들을 삭제하는것)

 

 str1.empty();

함수 원형 : bool empty() const;

함수 설명 : 스트링이 비었는지 확인하는 함수입니다. 비었으면 true를 반환합니다. 비었음의 기준은 size, length가 0인 것 입니다. capacity와는 관계가 없습니다.

함수 예시 : if(str1.empty()) { return true; }    //이런식으로 비었는지 확인하면됩니다. clear를 사용하고 empty를 사용하면 당연히 true 겠죠?

 

♣ string 가지고 놀기 종류

 str1.c_str()

함수 원형 : const char* c_str() const;

함수 설명 : C++ 스타일의 string 문자열을 C스타일의 문자열로 변경해주는 함수입니다. 

함수 예시 : const char* arr = str1.c_str();    // "BlockDMask"가 "BlockDMask\0"로 반환해 줍니다. C언어에서 처럼 사용할 수 있습니다.

 

 str1.substr(....)

함수 원형 : string substr(size_t index = 0, size_t len = npos) const;

함수 설명 : string을 index 에서부터 len만큼 잘라서 반환하는 함수입니다. 스트링 짤라서 반환. 두번째 인자의 len의 디폴트 npos가 의미하는 것은 "-1"입니다. size_t의 타입은 unsigned int 타입입니다. 그 unsigned int에 -1이 들어온다? 그게 무슨의미 일까요? 맞습니다. "언더플로우" 입니다. unsigned인 타입에 음수를 넣으면 제일 큰 값으로 세팅이 됩니다.  그렇기 때문에 npos에는 -1을 넣어서, 아무것도 넣지 않았을때는 항상 문자열이 길어질 수 있는 최대의 길이를 나타내게 됩니다.

 

함수 예시 : str1.substr();          //"BlockDMask" 그대로 반환합니다.

함수 예시 : str1.substr(5);        // "DMask"를 반환합니다. 0부터 세기 시작해서 "5" 번째 인자부터 끝까지의 문자열을 반환합니다.

함수 예시 : str1.substr(5, 1);     // "D"를 반환합니다. 5번째 인자부터, 1의 길이만큼 문자열을 반환합니다.

 

 str1.replace(....)

함수 원형 : string& replace(size_t index, size_t len, const string& str)

함수 설명 : 함수를 호출하는 문자열의 index위치에서 len 길이까지의 범위를 매개변수로 들어온 str 전체로 대체 하는 함수입니다.

함수 예시 : str1.replace(5, 2, str2);

// "BlockDMask"의 5번째 인자에서부터 2개를 str2로 대체하게 됩니다. 그러면 "BlockBlogBlogBlogBlogask" 이런식의 문자가 됩니다.

 

 str1.compare(....)

함수 원형 : int compare(const string& str2) const;

함수 원형 : int compare(size_t index, size_t len, const string& str2) const;

함수 원형 : int compare(size_t index, size_t len, const string& str2, size_t index2, size_t len2) const;

 

함수 설명 : 매개변수로 들어온 str을 비교해서 같으면 0을 반환하고, 다르면 0이 아닌 값을 반환하는 함수입니다. 호출하는 스트링의 값이 매개변수로 들어온 스트링의 값보다 작을때(사전순 빠를때) 음수(-1)를 반환하고 호출하는 스트링의 값이 매개변수로 들어온 스트링의 값보다 클때(사전순 느릴때) 양수(1)를 반환합니다

함수 예시 : str1.compare(str2);    // "BlockDMask", "BlogBlogBLogBLog"는 같지 않기 때문에 0이 아닌 값을 반환하고, Blo까지는 둘이 똑같고, 그다음 c, g를 비교하게 됩니다. 이때, c가 g보다 사전상 더 앞선글자이기 때문에 c가 더 작은 글자가 됩니다. 그렇기 때문에 음수(-1)를 반환하게 됩니다.

함수 예시 : str2.compare(str1);    // 이거는 그럼 양수(1)을 반환하겠죠?

함수 예시 : str1.compare("BlockDMask");    //이 경우에는 두 스트링이 같기 때문에 0을 반환합니다.

함수 예시 : str1.compare(0, 2, str2);    // str1인 "BlockDMask"의 0번째 인덱스 부터 길이가 2인 문자열 "Bl"과 str2인 "BlogBlogBlogBlog" 를 비교합니다. 두 문자열이 다르기 때문에 0이 아닌 수를 반환합니다.

함수 예시 : str1.compare(0, 2, str2, 4, 2); //str1의 "BlockDMask"의 0번째 인덱스 부터 길이 2인 문자열 "Bl"과 str2 문자열 "BlogBlogBlogBlog" 3번째 인덱스 부터 길이가 2인 문자열인 "Bl"을 비교합니다. 비교할 문자열이 같기 때문에 0을 반환합니다.

 

 str1.copy(....)

함수 원형 : size_t copy(char* arr, size_t len, size_t index = 0) const;

함수 설명 : 딱봐도 복사를 하는 함수입니다. 이거는 특이하게 길이는 나타내는 len이 두번째고, index가 세번째 인자입니다. 아무래도 시작하는곳이 더 중요하지 않다고 판단하고 디폴트 인자를 설정해주려고 맨뒤로 보낸걸로 보입니다.

 

첫번째 매개변수 : 호출한 문자열을 첫번째 매개변수 문자열에 복사하는 함수입니다. char* 인걸 보면, C언어의 문자열(배열타입)을 받습니다.

두번째 매개변수는 복사할 문자열의 길이를 나타냅니다.

세번째 매개변수는 복사를 시작할 위치 입니다. index는 0부터 시작하는거 아시죠?

마지막으로 실제로 복사된 길이, arr의 길이를 반환합니다.

함수 예시 : char arr[10];    //문자열을 복사해서 넣을 빈 배열을 만듭니다.

함수 예시 : int arrLen = str1.copy(arr, 3, 5);    //5번째 index부터 3의 길이만큼 복사 한다는 거니까 "BlockDMask" 빨간 부분이 들어갔을겁니다. 그리고 반환하는 arrLen은 3의 길이겠죠?

함수 예시 : arr[arrLen] = '\0';    //그리고 C의 문자열의 끝에는 '\0'이걸 넣어주어야 합니다. 그러면 문자열 복사가 깔끔하게 되었을 겁니다.

 

 str1.find(....)

함수 원형 : size_t find (const string& str, size_t index = 0) const;

함수 원형 : size_t find (const char* arr, size_t index = 0) const;

함수 설명 : 매개변수로 들어온 문자열과, 내 문자열중에 일치하는 게 있는지 확인하는 함수입니다.  만약에 일치하는게 있다면, 일치하는 부분의 첫번째 순서(index)를 반환합니다. 두번째 매개변수로 들어온 index는 어느 위치에서 부터 찾을까 입니다.

함수 예시 : str2.find("Blog");    // "BlogBlogBlogBlog" -> 0 을 반환합니다.

함수 예시 : str2.find("Blog", 5);    // 5번째 인자부터 blog를 찾게되니 BlogBlogBlogBlog 빨간색 l에서부터 찾게되므로 그 다음에 나오는 b의 위치인 8을 반환할 것 입니다.

 

 str1.push_back(c)

함수 원형 : void push_back(char c);

함수 설명 : 함수를 호출하는 스트링의 맨뒤에 문자 c를 더하는 함수 입니다.

함수 예시 : str1.push_back('a');    //"BlockDMask" -> "BlockDMaska" 'a'가 하나 더해집니다.

 

 str1.pop_back()

함수 원형 : void pop_back()

함수 설명 : 함수를 호출하는 스트링의 맨뒤에 있는 문자 하나를 없애는 함수 입니다.

함수 예시 : str1.pop_back();    // "BlockDMask" -> "BlockDMas" 이렇게 k가 하나 빠집니다.

 

♣ string iterator 종류

 str1.begin();

함수 원형 : iterator begin();

함수 원형 : const_iterator begin() const;

함수 설명 : 문자열의 첫 번째 문자를 가리키는 반복자(iterator 포인터)를 반환합니다.

 

 str1.end();

함수 원형 : iterator end();

함수 원형 : const_iterator end() const;

함수 설명 : 문자열의 마지막의 바로 다음을 가리키는 반복자(iterator 포인터)를 반환합니다. (잘 봐야해요 문자열 끝이 아니라 그 다음!)

iterator는 보통 순회를 할때 많이 사용합니다. 아래와 같은 방식으로 많이 쓰죠. 아래와 같이 하면, B 엔터 l 엔터 이런식으로 한글자씩 나오게 됩니다.

for (string::iterator iter = str1.begin(); iter != str1.end(); ++iter)
{
    cout << *iter << endl;
}

 

♣ string의 기타등등.

 swap(str1, str2);

함수 원형 : void swap(string& str1, string& str2);

함수 설명 : str1과 str2를 바꾸는 것 입니다. 스왑을 할때 복사를 해서 스왑을 하는것이 아니라 서로 참조(reference)를 교환해서 스왑을 합니다.  그렇기 때문에 복사에 의한 성능저하를 우려할 필요가 없습니다.

함수 예시 : swap(str1, str2);    //str1이 "blog~~"가 되고, str2가 "BlockDMask"가 됩니다.

 

 operator+

함수 설명 : 이거는 오퍼레이터 +인데요. string끼리 더할 수 있습니다. 더한다는 의미는 이어 붙인다는 것 입니다.

  이미 만들어져 있는 것이라, 우리가 그냥 string끼리 더해서 사용하면 됩니다. 

함수 예시 : str1 += str2;    //str1은 "BlockDMaskBlogBlogBlogBlog" 이런식으로 만들어집니다.

 

3. C++ string 클래스 예제1 (생성과 출력, 문자열 연결, push_back, pop_back)

//C++ string example1
//BlockDMask.
#include<iostream>
#include<string>
using namespace std;
 
int main()
{
    string str1 = "BlockDMask";
    string str2("BlogBlogBlogBlog");
    string str3(str1);
 
    //string을 생성하는 다양한 방법.
    cout << "==> onstructor" << endl;
    cout << "str1 = \"BlockDMask\" \n : " << str1 << endl << endl;
    cout << "str2(\"BlogBlogBlogBlog\") \n : " << str2 << endl << endl;
    cout << "str3(str1) \n : " << str3 << endl << endl;
 
    //push_back, pop_back
    cout << endl;
    cout << "==> string front, back example." << endl;
    str1.push_back('1');
    cout << "str1.push_back('1') : " << str1 << endl;
    str1.push_back('2');
    cout << "str1.push_back('2') : " << str1 << endl;
    str1.pop_back();
    cout << "str1.pop_back() :  " << str1 << endl;
    str1.pop_back();
    cout << "str1.pop_back() :  " << str1 << endl;
    str1.pop_back();
    cout << "str1.pop_back() :  " << str1 << endl;
 
    //operator+ stirng 덧셈.
    cout << endl;
    cout << "==> str1 += str2" << endl;
    str1 += str2;
    cout << str1 << endl;
           
    cout << endl;
    system("pause");
    return 0;
}

▲ C++ string 예제1 (생성과 출력, 문자열 연결, push_back, pop_back)

stirng을 생성하는 3가지 방법에 대한 예제

그리고 string끼리 연결하기, 더하기, 맨뒤에 문자 추가하기, 맨뒤에있는 문자 뺴기

 

4. C++ string 클래스 예제2 (size, capacity, length, clear, shrink_to_fit)

//C++ string example2
//BlockDMask.
#include<iostream>
#include<string>
using namespace std;
 
int main()
{
    string str2 = "BlogBlogBlogBlog";
 
    cout << "==> str2 original" << endl;
    cout << "str2 : " << str2 << endl;
    cout << "str2.size() : " << str2.size() << endl;
    cout << "str2.length() : " << str2.length() << endl;
    cout << "str2.capacity() : " << str2.capacity() << endl;
    
    cout << endl;
    str2.resize(4);
    cout << "==> str2.resize(4)" << endl;
    cout << "str2 : " << str2 << endl;
    cout << "str2.size() : " << str2.size() << endl;
    cout << "str2.length() : " << str2.length() << endl;
    cout << "str2.capacity() : " << str2.capacity() << endl;
 
    cout << endl;
    str2.shrink_to_fit();
    cout << "==> str2.shrink_to_fit()" << endl;
    cout << "str2 : " << str2 << endl;
    cout << "str2.size() : " << str2.size() << endl;
    cout << "str2.length() : " << str2.length() << endl;
    cout << "str2.capacity() : " << str2.capacity() << endl;
 
    cout << endl;
    str2.clear();
    cout << "==> str2.clear()" << endl;
    cout << "str2 : " << str2 << endl;
    cout << "str2.size() : " << str2.size() << endl;
    cout << "str2.length() : " << str2.length() << endl;
    cout << "str2.capacity() : " << str2.capacity() << endl;
 
    cout << endl;
    system("pause");
    return 0;
}

▲ C++ string 예제2 (size, capacity, length, clear, shrink_to_fit)

1. string에서 size와 length가 같은지.

2. string에서 capacity가 무엇인지.

3. resize(), shrink_to_fit() 함수와 clear() 함수도 살펴봐 주세요.

 

5. C++ string 클래스 예제3 (substr, replace, swap)

//C++ string example2
//BlockDMask.
#include<iostream>
#include<string>
using namespace std;
 
int main()
{
    string str2 = "BlogBlogBlogBlog";
 
    cout << "==> str2 original" << endl;
    cout << "str2 : " << str2 << endl;
    cout << "str2.size() : " << str2.size() << endl;
    cout << "str2.length() : " << str2.length() << endl;
    cout << "str2.capacity() : " << str2.capacity() << endl;
    
    cout << endl;
    str2.resize(4);
    cout << "==> str2.resize(4)" << endl;
    cout << "str2 : " << str2 << endl;
    cout << "str2.size() : " << str2.size() << endl;
    cout << "str2.length() : " << str2.length() << endl;
    cout << "str2.capacity() : " << str2.capacity() << endl;
 
    cout << endl;
    str2.shrink_to_fit();
    cout << "==> str2.shrink_to_fit()" << endl;
    cout << "str2 : " << str2 << endl;
    cout << "str2.size() : " << str2.size() << endl;
    cout << "str2.length() : " << str2.length() << endl;
    cout << "str2.capacity() : " << str2.capacity() << endl;
 
    cout << endl;
    str2.clear();
    cout << "==> str2.clear()" << endl;
    cout << "str2 : " << str2 << endl;
    cout << "str2.size() : " << str2.size() << endl;
    cout << "str2.length() : " << str2.length() << endl;
    cout << "str2.capacity() : " << str2.capacity() << endl;
 
    cout << endl;
    system("pause");
    return 0;
}

▲ C++ string 예제3 (size, capacity, length, clear, shrink_to_fit)

1. str1의 substr(5) : index가 5번째인 값부터 끝까지 문자열을 반환.

2. str1의 substr(5,1) : index가 5번째인 값부터 1 길이의 문자열을 반환.

3. str1.replace(5, 2, str2) : str1의 5번째인 자리부터 2개의 문자열을 str2문자열 전체로 대체.

4. swap(str2, str3) : str2와 str3의 참조를 서로 바꾸어줌.

 

6. C++ string 클래스 예제4 (find, operaotr[], at, front, back)

//C++ string example4.
//BlockDMask.
#include<iostream>
#include<string>
using namespace std;
 
int main()
{
    string str1 = "BlockDMask";
    string str2 = "BlogBlogBlogBlog";
 
    cout << "str1 : " << str1 << endl;
    cout << "str2 : " << str2 << endl;
    cout << endl;
 
    //find
    cout << "==> string find example." << endl;
    cout << "str1.find(\"DM\") : " << str1.find("DM") << endl;
    cout << "str2.find(\"Blog\") : " << str2.find("Blog") << endl;
    cout << "str2.find(\"Blog\", 5) : " << str2.find("Blog", 5) << endl;
 
    //operator[], at
    cout << endl;
    cout << "==> string operator[], at() example." << endl;
    cout << "str1[0] : " << str1[0] << endl;
    cout << "str1[3] : " << str1[3] << endl;
    cout << "str1[str1.size()-1] : " << str1[str1.size() - 1] << endl;
    cout << endl;
    cout << "str1.at(0) : " << str1.at(0) << endl;
    cout << "str1.at(3) : " << str1.at(3) << endl;
    cout << "str1.at(str1.size()-1) : " << str1.at(str1.size() - 1) << endl;
 
    //front, back
    cout << endl;
    cout << "==> string front, back example." << endl;
    cout << "str1[0] : " << str1[0] << endl;
    cout << "str1.at(0) : " << str1.at(0) << endl;
    cout << "str1.front() : " << str1.front() << endl;
    cout << endl;
    cout << "str1[str1.size()-1] : " << str1[str1.size() - 1] << endl;
    cout << "str1.at(str1.size()-1) : " << str1.at(str1.size() - 1) << endl;
    cout << "str1.back() : " << str1.back() << endl;
 
    cout << endl;
    system("pause");
    return 0;
}

▲ C++ string 예제4 (find, operator[], at, front, back)

1. find의 사용법.

2. string 인자 접근법. 

3. 그리고.. 맨앞과 맨 끝 접근법.

front vs str1[0]

back vs str1[str1.size()-1]

어떤걸 사용하시든, 개발하시는분 마음이지만 이왕이면 저는 front와 back을 추천합니다.

 

7. C++ string 클래스 예제5 (begin, end, copy, compare)

//C++ string example5
//BlockDMask.
#include<iostream>
#include<string>
using namespace std;
 
int main()
{
    string str1 = "BlockDMask";
    string str2 = "BlogBlogBlogBloc";
 
    cout << "str1 : " << str1 << endl;
    cout << "str2 : " << str2 << endl;
    cout << endl;
 
    //begin, end
    cout << "==> begin, end" << endl;
    string::iterator iter = str1.begin();
    for (; iter != str1.end(); ++iter)
    {
        cout << *iter << " ";
    }
    cout << endl;
 
    //copy
    cout << endl;
    cout << "==> copy " << endl;
    char arr[10];
    int arrLen = str1.copy(arr, 3, 5);
    cout << "str1.copy(arr, 3, 5)" << endl;
    cout << "arrLen : " << arrLen << endl;
    cout << arr << endl;    //error.
    arr[arrLen] = '\0';
    cout << arr << endl;    //ok.
 
    //compare
    cout << endl;
    cout << "==> compare" << endl;
    cout << "str1.compare(\"BlockDMask\") : " << str1.compare("BlockDMask") << endl;
    cout << "str1.compare(str2) : " << str1.compare(str2) << endl;
    cout << "str2.compare(str1) : " << str2.compare(str1) << endl;
    cout << endl;
    system("pause");
    return 0;
}

▲ C++ string 예제4 (find, operator[], at, front, back)

1. begin, end 반복자를 이용한 순회

2. copy를 했을때는 꼭 맨뒷자리에 '\0'을 잊지말아주세요. 저기 DMa 뒤에 쓰레기값이 들어가는거 보이시죠? 

  C언어에서, char 배열에서 문자열의 끝은 '\0' 한번 더 강조합니다.

3. compare는 같으면 0, 다르면 -1, 1 입니다. 

  -1은 불러주는 스트링이 사전순 앞

   1은 불러주는 스트링이 사전순 뒤

 

출처: www.crocus.co.kr/733

 

 

+ Recent posts