-
C, C ++ 표준 라이브러리와 STL 정리Problem Solving/PS를 위한 C++ 지식 2020. 3. 18. 22:19
C++ 표준 라이브러리<algorithm>
reverse
- 원소들을 거꾸로 뒤집어 준다.
[예제]
#include <string> #include <vector> #include <iostream> #include <algorithm> using namespace std; int main() { vector<int> arr = { 1,2,3,4,5 }; reverse(arr.begin(), arr.end()); for (int n : arr) cout << n << " "; cout << endl; string str = "Hello World!"; reverse(str.begin(), str.end()); cout << str << endl; cout << endl; vector<string> strArr = { "apple", "banana", "tomato", "peach" }; reverse(strArr.begin(), strArr.end()); for (string tmp : strArr) cout << tmp << " "; cout << endl; return 0; }
copy
- 배열 복사할때 유용하다.
- copy(원본의 시작 주소, 원본의 마지막 주소, 사본의 시작 주소);
- copy 함수는 [시작주소 , 마지막주소) 반열린 구간으로 동작된다. 따라서 원본의 마지막 주소 +1을 해줘야한다.
[예제 1 : n 크기의 1차원 배열 a를 1차원 배열 b에 복사하기]
#include<iostream> #include<algorithm> using namespace std; int a[5]; int b[5]; int main() { int n = 5; for (int i = 0; i < n; i++) { a[i] = 7; } copy(&a[0], &a[n-1] + 1, &b[0]); for (int i = 0; i < n; i++) { cout << b[i]; } return 0; }
[예제 2 : n x m 크기의 2차원 배열 a를 2차원 배열 b에 복사하기]
#include<iostream> #include<algorithm> using namespace std; int a[5][5]; int b[5][5]; int main() { int n = 5, m = 5; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { a[i][j] = 7; } } copy(&a[0][0], &a[n-1][m-1] + 1, &b[0][0]); for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { cout << b[i][j]; } cout << endl; } return 0; }
next_permutation, prev_permutation
- next_permutation : 특정 원소들의 다음 순열을 얻는다.
- prev_permutation : 특정 원소들의 이전 순열을 얻는다.
- 순열을 구할 때 유용하다, do while 문을 사용해서 쓴다.
- 주의 : 대상 배열(벡터)에 중복된 원소가 존재하면, 중복된 원소를 제거하고 순열을 구해준다.
- 사용전에 원소들이 오름차순으로 정렬된 상태여야 모든 순열을 구할 수 있다.
[예제 1 : next_permutation]
#include<iostream> #include<algorithm> using namespace std; int main() { int arr[5] = { 0,1,2,3,4 }; do { for (int n : arr) { printf("%d ", n); } puts(""); } while (next_permutation(arr, arr+5)); //다음 순열을 구한다. 다음 순열이 없으면 false return // 문자열에 대해서도 아래와 같이 가능하다. // 순열을 돌리면 31142 와 같은 숫자가 2번 나올 수 있다. // 하지만 next_permutation은 중복을 제거하기 때문에 1번만 나온다. string s = "31421"; sort(s.begin(), s.end()); do { cout << s << endl; } while (next_permutation(s.begin(), s.end())); return 0; }
[예제 2 : prev_permutation]
#include<iostream> #include<algorithm> using namespace std; int main() { int arr[5] = { 4,3,2,1,0 }; do { for (int n : arr) { printf("%d ", n); } puts(""); } while (prev_permutation(arr, arr+5)); //이전 순열을 구한다. 이전 순열이 없으면 false return return 0; }
fill
- 특정 범위를 어떤 값으로 채운다.
- fill(시작주소, 마지막주소, 채울 원소값);
- fill 함수는 [시작주소 , 마지막주소) 반열린 구간으로 동작된다. 따라서 원본의 마지막 주소 +1을 해줘야한다.
- <string.h>의 memset은 byte 단위로 동작하기 떄문에 정수나 문자에 대해 동작하지 않는다. 이때 fill을 쓰면 된다.
[예제 1 : 1차원 배열 arr을 7로 채우기]
#include<iostream> #include<algorithm> using namespace std; int main() { int arr[10]; fill(&arr[0], &arr[9]+1, 7); //마지막 주소를 포함하지 않은 반열린 구간이기에 +1을 해준다. for (int i = 0; i < 10; i++) cout << arr[i] << endl; return 0; }
[예제 2 : 2차원 배열 arr을 7로 채우기]
#include<iostream> #include<algorithm> using namespace std; int main() { int arr[10][10]; fill(&arr[0][0], &arr[9][9] +1 , 7); for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { cout << arr[i][j]; } puts(""); } return 0; }
✔️ sort 함수
특정 원소들을 정렬 시켜준다.
◾ fill 함수는 [시작주소 , 마지막주소) 반열린 구간으로 동작된다. 따라서 원본의 마지막 주소 +1을 해줘야한다.
◾ sort(시작주소, 마지막 주소, less<자료형>()); // defalut 오름차순이다.
◾ sort(시작주소, 마지막 주소, greater<자료형>()); //이렇게 해주면 내림차순으로 동작한다.
💾 [예제 1 : 1차원 배열 arr 정렬]
더보기#include<iostream> #include<algorithm> using namespace std; int main() { int arr[10] = { 4,7,2,9,5,0,8,1,6,3 }; sort(arr, arr + 10); //오름차순 for (int i = 0; i < 10; i++) { cout << arr[i] << " "; } cout << endl; sort(arr, arr + 10, greater<int>()); //내림차순 for (int i = 0; i < 10; i++) { cout << arr[i] << " "; } return 0; }
💾 [예제 2 : 1차원 vector arr 정렬]
더보기#include<iostream> #include<algorithm> #include<vector> using namespace std; int main() { vector<int> arr{ 4,7,2,9,5,0,8,1,6,3 }; sort(arr.begin(), arr.end()); for (int i = 0; i < 10; i++) { cout << arr[i] << " "; } cout << endl; sort(arr.begin(), arr.end(), greater<int>()); for (int i = 0; i < 10; i++) { cout << arr[i] << " "; } return 0; }
💾 [예제 3 : compare 함수를 통해 구조체 정렬하기]
더보기#include<iostream> #include<algorithm> #include<vector> #include<string> using namespace std; typedef struct { string name; int age; }person; //이름을 사전순으로 정렬하되, 이름이 같으면 나이가 적은 순서로 정렬 bool compare_1(person a, person b) { if (a.name == b.name) return a.age < b.age; // 2.이름이 같으면, 나이가 적은 순으로 정렬 else return a.name < b.name; // 1.이름을 사전순으로 정렬 } //나이가 적은 순서로 정렬하되, 나이가 같으면 이름을 사전순으로 정렬 bool compare_2(person a, person b) { if (a.age == b.age) // 2.나이가 같으면 이름을 사전순으로 정렬 return a.name < b.name; else return a.age < b.age; // 1.나이가 적은 순서로 정렬 } int main() { vector<person> arr; arr.push_back({ "eee", 15}); arr.push_back({ "ccc", 4 }); arr.push_back({ "eee", 1 }); arr.push_back({ "bbb", 3 }); arr.push_back({ "ccc", 7 }); arr.push_back({ "aaa", 2 }); arr.push_back({ "fff", 1 }); arr.push_back({ "eee", 7 }); sort(arr.begin(), arr.end(), compare_1); puts("compare_1"); for (int i = 0; i < arr.size(); i++) { cout << arr[i].name << " "; cout << arr[i].age << endl; } puts(" "); puts("compare_2"); sort(arr.begin(), arr.end(), compare_2); for (int i = 0; i < arr.size(); i++) { cout << arr[i].name << " "; cout << arr[i].age << endl; } return 0; }
👀 결과
예제3 결과
min, max
- min, max를 사용해 최대, 최소값을 구할 수 있다.
- 두 개의 원소에 대해서만 가능, 3개하고 싶으면 min(a, min(b,c)); 이렇게하면 된다.
[예제 1 : a, b 중 최대, 최소 구하기]
#include<iostream> #include<algorithm> using namespace std; int main() { int a = -9999, b = 9999; int res; res = min(a, b); cout << res << endl; res = max(a, b); cout << res << endl; return 0; }
swap
- 두 원소의 값을 교환한다.
#include<iostream> #include<algorithm> using namespace std; int main() { int a = 2, b = 5; swap(a, b); cout << a << endl; cout << b << endl; return 0; }
C++ 표준 템플릿 라이브러리(STL : Standard Template Library)
- c++ 표준 라이브러리는 꽤 많은 종류의 라이브러리들이 있다. (iostream, chrono, regex)
- 하지만 보통 C++ 템플릿 라이브러리(STL)을 일컫는다면, 아래와 같은 3개의 라이브러리를 의미한다.
- 임의 타입의 객체를 보관할 수 있는 컨테이너(container)
- 컨테이너에 보관된 원소에 접근할 수 있는 반복자(iterator)
- 반복자들을 가지로 일련의 작업을 수행하는 알고리즘(algorithm)
- 반복자는 컨테이너 원소에 접근할 수 있는 포인터와 같은 객체이다.
반복자(iterator)
◾ 반복자(iterator)란 STL 컨테이너에 저장된 요소를 반복적으로 순회하여, 각각의 요소에 대한 접근을 제공하는 객체입니다.
◾ 즉, 컨테이너의 구조나 요소의 타입과는 상관없이 컨테이너에 저장된 데이터를 순회하는 과정을 일반화한 표현입니다.
◾ 템플릿이 타입과 상관없이 알고리즘을 표현할 수 있게 해준다면, 반복자는 컨테이너와 상관없이 알고리즘을 표현할 수 있게 해주는 것입니다.
◾ 반복자가 가져야 할 요구 사항과 정의되어야 할 연산자는 다음과 같습니다.
1. 가리키는 요소의 값에 접근할 수 있어야 합니다. 따라서 참조 연산자(*)가 정의되어야 합니다.
2. 반복자 사이의 대입 연산, 비교 연산이 가능해야 합니다. 따라서 대입, 관계 연산자가 정의되어야 합니다.
3. 가리키는 요소의 주변 요소로 이동할 수 있어야 합니다. 따라서 증가 연산자(++)가 정의되어야 합니다.
위와 같은 요구 사항을 모두 갖춰야만 STL 알고리즘에서 반복자로 사용될 수 있습니다.
순차 컨테이너(Sequence Container)
- 순차 컨테이너는 배열 처럼 객체를 순차적으로 보관한다.
- vector, deque, list 등이 있다.
vector
- 가변 길이 배열이다. <vector>에 정의되어 있다.
- 원소들이 메모리 상에 실제로 순차적으로 저장되어 있다.
- 따라서 임의의 위치에 있는 원소에 접근하는 것을 매우 빠르게 수행할 수 있다.
- [ ] 을 통해 임의의 위치 원소에 접근할 수 있다.
- size : vector의 사이즈를 리턴한다.
- push_back : 맨 뒤에 원소를 추가한다.
- pop_back : 맨 뒤의 원소를 제거한다.
- insert : 임의의 위치에 원소를 추가한다.
- erase : 임의의 위치의 원소를 제거한다.
- begin : vector의 첫번째 원소를 가리키는 반복자를 리턴한다.
- end : vector의 마지막원소 한 칸 뒤를 가리키는 반복자를 리턴한다.
- clear : 원소를 모두 제거한다.
vector 기본예제
#include<iostream> #include<vector> #include<algorithm> using namespace std; int main() { vector<int> arr; //맨뒤에 원소 추가 arr.push_back(1); arr.push_back(2); arr.push_back(3); //배열처럼 임의 원소에 O(1)로 접근 가능 printf("%d %d %d %d\n", arr.size(), arr[0], arr[1], arr[2]); //맨뒤의 원소 제거 arr.pop_back(); arr.pop_back(); arr.pop_back(); //벡터 사이즈 출력 printf("%d\n", arr.size()); arr.push_back(1); arr.push_back(3); arr.push_back(5); arr.push_back(6); arr.push_back(7); //임의 위치에 데이터 추가 arr.insert(arr.begin() + 1, 2); // arr[1]위치에 2를 넣는다. arr[1]은 뒤로 밀림 arr.insert(arr.begin() + 3, 4); // arr[3]위치에 4를 넣는다. arr[3]은 뒤로 밀림 //임의 위치의 데이터 제거 arr.erase(arr.begin() + 5); arr.erase(arr.begin() + 5); for (int i = 0; i < arr.size(); i++) { printf("%d ", arr[i]); } puts(""); // iterator 활용 sort(arr.begin(), arr.end(), greater<int>()); for (int i = 0; i < arr.size(); i++) { printf("%d ", arr[i]); } cout << endl; //모든 원소 삭제 arr.clear(); printf("\n after clear, arr size = %d\n", arr.size()); // 1차원 vector 초기화 : 크기 10의 벡터를 만들고 5로 초기화 vector<int> v1(10, 5); //vector<int> v = vector<int>(10, 7); //이와 같이 초기화할 수 있다. for (int i = 0; i < 10; i++) { cout << v1[i]; } cout << endl; cout << endl; // 2차원 vector 초기화 : 크기 10x10의 벡터를 만들고 7로 초기화 vector<vector<int>> v2(10, vector<int>(10, 7)); for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { cout << v2[i][j]; } cout << endl; } return 0; }
vector 초기화 예제
#include <vector> #include <iostream> using namespace std; int main() { vector<int> arr1(5); // 원소 5개를 만들고 0으로 초기화한다. for (int i = 0; i < arr1.size(); i++) { cout << arr1[i]; } cout << endl; cout << endl; vector<int> arr2(7, 7); for (int i = 0; i < arr2.size(); i++) { cout << arr2[i]; } cout << endl; cout << endl; vector<vector<string>> arr3(5, vector<string>(4, "abcd")); // 복잡한 vector 초기화 for (int i = 0; i < arr3.size(); i++) { for (int j = 0; j < arr3[i].size(); j++) { cout << arr3[i][j][0] <<" " << arr3[i][j][1] << " " << arr3[i][j][2] << " " << arr3[i][j][3] << endl; } cout << endl; } return 0; }
deque
- 양쪽에서 끝나는 큐(double ended queue)로 <deque>에 정의되어 있다.
- 다른 순차 컨테이너처럼 deque도 선형으로 메모리 상에 위치한다. 하지만 vector와 달리 deque는 모든 원소가 메모리 상에 연속적으로 존재한다고 보장할 수 없다. vector는 capacity가 꽉 찼을 경우 새롭게 크게 한 덩어리의 메모리를 할당하지만, deque는 메모리 상에서 잘게 쪼개서 보관한다. vector에 비해 조금 복잡하지만 메모리 공간을 효율적으로 사용할 수 있다.
- begin : 첫번째 원소를 가리키는 반복자를 리턴한다.
- end : 끝 부분을 가리키는 반복자를 리턴한다.
- size : deque의 현재 원소의 개수를 리턴한다.
- empty : deque이 비어있는지 체크한다.
- front : 첫 번째 원소에 접근한다.
- back : 마지막 원소에 접근한다.
- push_back : 원소를 끝에 추가한다.
- push_front : 원소를 맨 앞에 추가한다.
- pop_back : 마지막 원소를 제거한다.
- pop_front : 첫 번째 원소를 제거한다.
- erase : 원소를 제거한다.
- clear : 원소를 모두 제거한다.
- [ ] 을 통해 임의의 위치 원소에 접근할 수 있다.
#include<iostream> #include<deque> #include<algorithm> using namespace std; int main() { deque<int> dq; dq.push_back(3); dq.push_back(4); dq.push_front(2); dq.push_front(1); while (!dq.empty()) { printf("%d ", dq.front()); dq.pop_front(); } puts(""); dq.push_back(1); dq.push_back(2); dq.push_back(3); dq.push_back(4); while (!dq.empty()) { printf("%d ", dq.back()); dq.pop_back(); } puts(""); dq.push_back(1); dq.push_back(2); dq.push_back(3); dq.push_back(4); printf("deque size = %d\n", dq.size()); dq.clear(); printf("after clear, deque size = %d\n", dq.size()); return 0; }
list
- [ ] 접근 불가능
컨테이너 어댑터(Container Adaptor)
◾ 컨테이너 어댑터는 반복자(iterator)를 지원하지 않는다.
stack
- LIFO(Last In First Out), <stack>에 정의
- push : stack push
- pop : stack pop
- top : 가장 위에 있는 원소를 가져온다.
- empty : stack이 비어있으면 true 그렇지 않으면 false 반환
- size : stack의 원소수 반환
- 참고 : stack이 empty일 때, stack.top() 하면 런타임 오류남(empty 체크 먼저 해야함)
#include<iostream> #include<stack> using namespace std; int main() { stack<int> st; st.push(1); st.push(2); st.push(3); st.push(4); while (!st.empty()){ printf("스택 사이즈 : %d, pop한 원소 : %d\n",st.size(), st.top()); st.pop(); } return 0; }
queue
- FIFO(First In First Out), queue<int>에 정의
- push : enqueue
- pop : dequeue
- front : 가장 앞에 있는 원소 반환
- back : 가장 뒤에 있는 원소 반환
- empty : queue가 비어있으면 true 아니면 false 반환
- size : queue 사이즈를 반환
#include<iostream> #include<queue> using namespace std; int main() { queue<int> q; q.push(1); q.push(2); q.push(3); q.push(4); printf("q.size() : %d, q.front() : %d, q.back() : %d\n",q.size(), q.front(), q.back()); q.pop(); q.pop(); printf("q.size() : %d, q.front() : %d, q.back() : %d\n", q.size(), q.front(), q.back()); q.pop(); q.pop(); if (q.empty()) printf("큐가 비어있습니다."); return 0; }
priority_queue
- defalut는 max heap이다.
- min heap을 쓰고 싶다면, 값을 음수로 바꿔서 넣어준다. https://koosaga.com/9
- 우선순위 큐는 실제로는 priority_queue<자료형, 구현체, 비교 연산자>로 정의하는 것을 알 수 있다.
- 자료형은 int, double, 선언한 클래스
- 구현체는 기본적으로 vector<자료형>으로 정의
- 비교 연산자는 기본적으로 less<자료형>으로 정의된다(MAX 힙)
- 비교 연산자를 greater<자료형> 으로 정의하면, min heap이 된다.
- Pair을 힙에 넣으면 first, second 순으로 힙이 작동한다.
✔️ 연관컨테이너
◾ 연관 컨테이너는 순차 컨테이너와는 다르게 키(key) - 값(value) 구조를 가진다.
◾ 특정한 키를 통해 대응되는 값을 얻을 수 있다.
◾ 중복된 원소(키)를 허용하지 않는다.
◾ Set과 Map은 내부적으로 BST(Red-Black Tree)로 구현되어있기 때문에 O(logN) 시간에 키에 접근할 수 있다.
◾ Set과 Map은 앞서 말했듯이 Red-Black Tree로 구현 되었기에 삽입, 삭제 연산에서 상당히 많은 작업이 발생할 수 있으므로 시간 복잡도 증가에 유의 해야한다.
1️⃣ Set
◾ 특정 키가 연관 컨테이너에 존재하는지 유무를 알 수 있다.
◾ Set은 키만 보관하고 키의 존재 여부를 알 수 있다.
💾 Set.cpp
더보기#include<iostream> #include<set> using namespace std; int main() { set<int> s; s.insert(1); s.insert(2); s.insert(3); s.insert(4); cout << "1이 셋에 존재해? : " << s.count(1) << endl; // 1의 개수 반환(0아니면 1) cout << "2가 셋에 존재해? : " << s.count(2) << endl; cout << "3이 셋에 존재해? : " << s.count(3) << endl; cout << "4가 셋에 존재해? : " << s.count(4) << endl; cout << "5가 셋에 존재해? : " << s.count(5) << endl; puts(""); puts("이터레이터를 통한 모든 원소 조회"); for (auto it = s.begin(); it != s.end(); it++) cout << *it << endl; return 0; }
2️⃣ map
◾ key와 value로 구성되어있다.
◾ 특정 키에 대응 되는 값이 무엇인지 알 수 있다.
💾 map.cpp
더보기#include<iostream> #include<string> #include<map> using namespace std; int main() { map<string, int> m; m.insert({ "박병욱", 26 }); m.insert({ "김규식", 24 }); m.insert({ "이기택", 28 }); m.insert({ "이기택", 25 }); // map은 중복된 원소를 허락하지 않는다. 왼쪽 코드는 무시됨. //아래와 같이 배열 형태로 원소를 추가할 수 있다. /* m["박병욱"] = 26; m["김규식"] = 24; m["이기택"] = 28; */ /*count는 원소의 유무를 알려준다. 1 또는 0 반환*/ cout << m.count("박병욱") << endl; cout << m.count("김규식") << endl; cout << m.count("이기택") << endl; //operator [] 연산은 key가 없을 경우 map에 {key: default} 값이 "삽입"된다. /* cout << m["박병욱"] << endl; cout << m["김규식"] << endl; cout << m["이기택"] << endl; */ //find는 key가 없을 경우 map에 데이터를 삽입하지 않음. cout << m.find("박병욱")->second << endl; cout << m.find("김규식")->second << endl; cout << m.find("이기택")->second << endl; //이터레이터를 통해 map을 아래와 같이 조회할 수 있다. (키 기준 오름차순 출력) for (auto it = m.begin(); it != m.end(); it++) { cout << it->first << " " << it->second << endl; } //이터레이터를 통해 map을 아래와 같이 조회할 수 있다. (키 기준 내림차순 출력) for(auto it = m.rbegin(); it != m.rend(); it++){ cout << it->first << " " << it->second << endl; } return 0; }
문자열
substr, replace
- <string>에 정의되어있다.
- size(), length() : string의 길이를 반환한다.
- clear(), : 스트링을 지운다.
- substr(index, len) : index부터 len만큼 잘라서 반환한다.
- replace(시작주소, len, '문자열1') : 시작주소부터 len길이까지의 범위를 '문자열1' 로 대체한다.
#include<iostream> #include<string> using namespace std; int main() { string s1 = "hello world!"; string s2 = "HELLO world!"; cout << s1.substr(0, 5) << endl; // index 0부터 길이 5만큼 자른다. cout << s1.substr(6) << endl; // index 6부터 끝까지 자른다. s1.replace(0, 5, "HELLO"); // index 0부터 길이 5만큼 "HELLO" 문자열로 대체한다. cout << s1 << endl; if (s1.compare(s2) == 0) // 문자열 s1과 s2를 비교한다. cout << "s1, s2 same"; return 0; }
한글을 잘라보자. (영어는 1바이트 한글은 2바이트이므로 고려해서 잘라줘야함.)
#include<iostream> #include<string> using namespace std; int main() { string str = "대한민국"; cout << str.substr(0, 2) << endl; cout << str.substr(2, 2) << endl; cout << str.substr(4, 2) << endl; cout << str.substr(6, 2) << endl; }
compare
- compare('비교할 문자열') : '비교할 문자열'과 비교해서 같으면 0, 다르면 사전상 순서에 따라 -1 또는 1을 반환한다.
#include<iostream> #include<string> using namespace std; int main() { string a = "abcd"; string b = "efgh"; if (a.compare(b) == 0) { cout << "두 문자열은 같습니다."; } else if (a.compare(b) < 0) { cout << "a가 b보다 사전순으로 앞 입니다."; }else if (a.compare(b) > 0) { cout << "a가 b보다 사전순으로 뒤 입니다."; } return 0; }
stoi
- <string>에 정의되어있다.
- string을 int 형으로 바꿔준다.
- c++ 11부터 가능하다.
#include<iostream> #include<string> using namespace std; int main() { string str = "123"; int num; num = stoi(str); cout << num; return 0; }
substr
◾ 문자열의 일부를 반환한다.
◾ substr(첫 번째 문자열의 인덱스, 부분 문자열의 길이)
#include<iostream> #include<string> using namespace std; int main() { string str = "ABCDEFG"; cout << str.substr(1) << endl; //1번 인덱스부터 끝까지 자른다. cout << str.substr(3) << endl; //3번 인덱스부터 끝까지 자른다. cout << str.substr(1, 2) << endl; //1번 인덱스부터 2개만큼 자른다. cout << str.substr(1, 3) << endl; cout << str.substr(1, 4) << endl; cout << str.substr(1, 5) << endl; cout << str.substr(2, 4) << endl;//2번 인덱스부터 4개만큼 자른다. cout << str.substr(3, 2) << endl; cout << str << endl; return 0; }
to_string
- <string>에 정의되어있다.
- int를 string으로 바꿔준다.
isdigit
문자숫자라면 1반환
아니라면 0반환
tolower, toupper
◾ tolower(c); : 문자 c를 소문자로 바꾼다.
◾ toupper(c); : 문자 c를 대문자로 바꾼다.
#include<string> #include<iostream> using namespace std; int main() { string str1 = "ABCDE"; string str2 = "abcde"; for (int i = 0; i < str1.size(); i++) { str1[i] = tolower(str1[i]); } cout << str1 << endl; for (int i = 0; i < str1.size(); i++) { str2[i] = toupper(str2[i]); } cout << str2 << endl; return 0; }
istringstream
◾ istringstream을 사용하여 공백을 기준으로 문자열을 자를 수 있다.
#include<iostream> #include<sstream> using namespace std; int main() { string str1 = "동해물과 백두산이 마르고 닳도록"; istringstream iss(str1); string a, b, c, d; iss >> a; iss >> b; iss >> c; iss >> d; cout << a << " " << b << " " << c << " " << d << endl; return 0; }
find
◾ 문자열에서 원하는 문자열의 위치를 찾는다.
◾ 원하는 문자열이 없으면 npos를 리턴한다.npos는string::npos로 정의되는 상수 이다.
#include<iostream> using namespace std; int main() { string str = "hello beautiful world"; // 문자열을 찾는데 성공하였다면, 해당 문자열의 시작 위치를 반환한다. cout << str.find("hello") << endl; cout << str.find("beautiful") << endl; cout << str.find("world") << endl; // 문자열을 찾지 못한다면 npos 를 리턴한다. // npos 는 string::npos로 정의되는 상수이다. cout << str.find("bad") << endl; if (str.find("bad") == string::npos) cout << "찾으시는 문자열이 없어요." << endl; return 0; }
그 외 라이브러리들
accumulate <numeric>
- accumulate(arr.begin(), arr.end(), 0) // 컨테이너의 합을 구해준다. 0은 초기값.
memset - <cstring>
- 특정 범위를 어떤 값으로 채운다.
- memset(시작주소, 값, 채울 구조의 사이즈);
- memset은 byte 단위로 동작된다. 따라서 0, char 등 1byte 단위로만 초기화가 가능하다.
distance
◾ 두 반복자의 거리를 반환해준다.
#include<vector> #include<iostream> using namespace std; int main() { vector<int> v(5, 1); cout << distance(v.begin(), v.end()); //5 cout << distance(v.begin()+2, v.end()); //3 return 0; }
lower_bound
◾ lower_bound(begin(), end(), value)
◾ [ begin(), end() ) 범위에서 value 이상의 값이 처음 나타나는 위치를 반환한다.
◾ 이진탐색으로 구현되어있다. O(logN)
#include <iostream> #include <vector> #include <algorithm> using namespace std; int main() { vector<int> v{ 1,2,3,4,5,10,9,8,7,6 }; sort(v.begin(), v.end()); vector<int>::iterator it = lower_bound(v.begin(), v.end(), 3); // 3이상이 나타나는 최초 위치 반환 cout << *it; return 0; }
upper_bound
◾ upper_bound(begin(), end(), value)
◾ [ begin(), end() ) 범위에서 value 초과의 값이 처음 나타나는 위치를 반환한다.
◾ 이진탐색으로 구현되어있다. O(logN)
#include <iostream> #include <vector> #include <algorithm> using namespace std; int main() { vector<int> v{ 1,2,3,4,5,10,9,8,7,6 }; sort(v.begin(), v.end()); vector<int>::iterator it = upper_bound(v.begin(), v.end(), 3); // 3보다 큰 값이 나타나는 최초 위치 반환 cout << *it; return 0; }
✔️ C 표준 라이브러리
c : <math.h>, c++ : <cmath>
#include<cmath> #include<iostream> using namespace std; int main() { int a = 2, b = 16, c = 32, d = 7; cout << pow(a, 1) << endl;//2 cout << pow(a, 2) << endl;//4 cout << pow(a, 3) << endl;//8 cout << pow(a, 4) << endl;//16 cout << pow(a, 10) << endl;//1024 cout << pow(b, 2) << endl;//256 cout << pow(c, 2) << endl;//1024 cout << pow(d, 2) << endl;//49 return 0; }
◾ sqrt(n) : 루트 n을 반환한다.
#include<cmath> #include<iostream> using namespace std; int main() { int a = 2, b = 16, c = 32; cout << sqrt(a) << endl; //1.14121 cout << sqrt(b) << endl; //4 cout << sqrt(c) << endl; //5.65685 return 0; }
✔️ cin, cout 속도 빠르게 하기
◾ scanf, printf와 함께 사용하면 안된다.
◾ 싱글 쓰레드 환경에서만 사용 가능하다.
#include<cmath> #include<iostream> using namespace std; int main() { ios_base :: sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); int num; for(int i=0; i<100000; i++){ cin>>num; cout<<num; } return 0; }
참고