제15장 STL과 람다식 STL의 개념을 이해하고 사용할 수 있다. 람다식을 이해하고 사용할 수 있다.
이번 장에서 만들어 볼 프로그램 (1) 영어 사전을 만들어보자. (2) 리포트 복사를 검사하는 프로그램을 작성해보자.
표준 템플릿 라이브러리(STL)
컨테이너 컨테이너는 자료를 저장하는 창고와 같은 역할을 하는 구 조이다. 즉 배열이나 연결 리스트, 벡터, 집합, 사전, 트리 등이 여기에 해당한다.
반복자 반복자(iterator)는 컨테이너의 요소를 가리키는 데 사용 된다. 반복자는 실제로 컨테이너와 알고리즘 사이의 다리 역할을 한다.
알고리즘 탐색(find): 컨테이너 안에서 특정한 자료를 찾는다. 정렬(sort): 자료들을 크기순으로 정렬한다. 반전(reverse): 자료들의 순서를 역순으로 한다. 삭제(remove): 조건이 만족되는 자료를 삭제한다. 변환(transform): 컨테이너의 요소들을 사용자가 제공하 는 변환 함수에 따라서 변환한다.
STL의 장점 STL은 프로그래밍에 매우 유용한 수많은 컨테이너와 알 고리즘을 제공한다.
컨테이너 벡터(vector): 동적 배열처럼 동작한다. 뒤에서 자료들이 추가 된다. 큐(queue): 데이터가 입력된 순서대로 출력되는 자료 구조 스택(stack): 먼저 입력된 데이터가 나중에 출력되는 자료 구조 우선 순위큐(priority queue): 큐의 일종으로 큐의 요소들이 우 선 순위를 가지고 있고 우선 순위가 높은 요소가 먼저 출력되 는 자료 구조 리스트(list): 벡터와 유사하지만 중간에서 자료를 추가하는 연 산이 효율적이다. 집합(set): 중복이 없는 자료들이 정렬되어서 저장된다. 맵(map): 키-값(key-value)의 형식으로 저장된다. 키가 제시되 면 해당되는 값을 찾을 수 있다.
컨테이너의 분류
예제 #include <iostream> #include <time.h> #include <list> using namespace std; int main() { list<int> values; srand(time(NULL)); for (int i = 0; i < 10; i++) { values.push_back(rand()%100); } values.sort(); for (auto& e: values){ std::cout << e << ' '; std::cout << endl; return 0;
예제
반복자 반복자: 일반화된 포인터(generalized pointer)
반복자 반복자: 일반화된 포인터(generalized pointer)
시퀀스
반복자의 연산자 컨테이너에서 다음 요소를 가리키기 위한 ++ 연산자 컨테이너에서 이전 요소를 가리키기 위한 -- 연산자 두개의 반복자가 같은 요소를 가리키고 있는 지를 확인하기 위한 == 와 != 연산자 반복자가 가리키는 요소의 값을 추출하기 위한 역참조 연산자 *
예제 ① vector<int> vec; // 벡터 선언 ② vector<int>::iterator it; // 반복자 선언 ③ for(it = vec.begin(); it != c.end(); it++) ④ cout << *it << " ";
반복자의 종류 전향 반복자(forward iterator): ++ 연산자만 가능하다. 양방향 반복자(bidirectional iterator): ++ 연산자와 -- 연산 자가 가능하다. 무작위 접근 반복자(random access iterator): ++ 연산자 와 -- 연산자, [ ] 연산자가 가능하다.
Old C++ 버전 #include <iostream> #include <vector> using namespace std; int main() { vector<int> v; v.push_back(1); v.push_back(2); v.push_back(3); for (vector<int>::iterator p = v.begin(); p != v.end(); ++p) cout << *p << endl; return 0; }
C++14 버전 #1 #include <iostream> #include <vector> using namespace std; int main() { vector<int> v; v.push_back(1); v.push_back(2); v.push_back(3); for (auto p = v.begin(); p != v.end(); ++p) cout << *p << endl; return 0; }
C++14 버전 #2 #include <iostream> #include <vector> using namespace std; int main() { vector<int> v; v.push_back(1); v.push_back(2); v.push_back(3); for (auto& n : v ) cout << n << endl; return 0; }
컨테이너의 함수
덱
예제 #include <iostream> #include <deque> using namespace std; int main() { deque<int> dq = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; dq.pop_front(); // 앞에서 삭제 dq.push_back(11); // 끝에서 추가 for (auto& n : dq) cout << n << " "; cout << endl; return 0; }
예제 int main() { deque<string> dq = { "naver", "daum", "cnn", "yahoo", "google" }; dq.push_front("infinity"); // 앞에서 삭제 dq.pop_back(); // 끝에서 추가 for (auto& e : dq) cout << e << " "; cout << endl; return 0; }
리스트
리스트
예제 #include <list> using namespace std; int main() { list<int> my_list={ 10, 20, 30, 40 }; auto it = my_list.begin(); it++; my_list.insert(it, 25); for (auto& n : li) cout << n << " "; cout << endl; return 0; }
집합
예제 int main() { set<int> my_set; my_set.insert(1); auto pos = my_set.find(2); if (pos != my_set.end()) cout << "값 " << *pos << "가 발견되었음" << endl; else cout << "값이 발견되지 않았음" << endl; return 0; }
Lab: 리포트 복사 검사 프로그램
예제 #include <iostream> #include <vector> #include <algorithm> #include <iterator> #include <sstream> #include <string> #include <set> using namespace std; int main() { string report1 = "This is a original report."; string report2 = "This is a copy report."; vector<string> v1; vector<string> v2; // 첫 번째 리포트를 단어로 분리하는 과정 istringstream iss1(report1); for (string s; iss1 >> s; ) v1.push_back(s);
예제 // 두 번째 리포트를 단어로 분리하는 과정 istringstream iss2(report2); for (string s; iss2 >> s; ) v2.push_back(s); sort(v1.begin(), v1.end()); sort(v2.begin(), v2.end()); vector<string> common; set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), back_inserter(common)); cout << "report1=" << report1 << endl; cout << "report2=" << report2 << endl << endl;
예제 cout << "공통적인 단어: "; for (string e : common) cout << e << ' '; cout << endl; return 0; }
Map
예제 #include <iostream> #include <map> #include <string> #include <iterator> using namespace std; int main() { map<string, string> myMap; myMap.insert(make_pair("김철수", "010-123-5678")); myMap.insert(make_pair("홍길동", "010-123-5679")); myMap["최자영"] = "010-123-5680";
예제 // 모든 요소 출력 for(auto& it : myMap){ cout << it.first << " :: " << it.second << endl; } if (myMap.find("김영희") == myMap.end()) cout << "단어 '김영희'는 발견되지 않았습니다. " << endl; return 0;
Lab: 영어사전 Map을 가지고 영어 사전을 구현해보자. 사용자로부터 단 어를 받아서 단어의 설명을 출력한다.
예제 #include <iostream> #include <string> #include <map> using namespace std; int main() { map<string, string> dic; dic["boy"] = "소년"; dic["school"] = "학교"; dic["office"] = "직장"; dic["house"] = "집"; dic["morning"] = "아침"; dic["evening"] = "저녁";
예제 string word; while (true) { cout << "단어를 입력하시오: "; cin >> word; if (word == "quit") break; string meaning = dic[word]; if (meaning != "") cout << word << "의 의미는 " << meaning << endl; } return 0;
Lab: 단어 빈도 계산하기 Map을 이용하여서 사용자로부터 문장을 받아들이고 각 단어가 나오는 빈도를 계산하는 프로그램을 작성하여 보 자.
예제 #include <iostream> #include <string> #include <map> using namespace std; int main() { map<string, int> table; string s; cout << "문장을 입력하시오(종료는 Ctrl-Z): "; while (true) { cin >> s; table[s]++; if (cin.eof()) break; } for (auto& iter = table.begin(); iter != table.end(); iter++) { cout << iter->first << " : " << iter->second << endl; return 0;
스택
예제 int main() { stack<string> st; string sayings[3] = { "The grass is greener on the other side of the fence", "Even the greatest make mistakes", "To see is to believe" }; for (auto& s : sayings) st.push(s); while (!st.empty()) { cout << st.top() << endl; st.pop(); } return 0;
큐
예제 int main() { queue<int> qu; qu.push(100); qu.push(200); while (!qu.empty()) { cout << qu.front() << endl; qu.pop(); } return 0;
STL 알고리즘
find()와 find_if() 함수 int main() { vector<string> vec { "사과", "토마토", "배", "수박", "키위" }; auto it = find(vec.begin(), vec.end(), "수박"); if (it != vec.end()) cout << "수박이 " << distance(vec.begin(), it) << "에 있습니 다." << endl; return 0; }
count() 함수 template <typename T> bool is_even(const T& num) { return (num % 2) == 0; } int main() vector<int> vec; for (int i = 0; i<10; i++) vec.push_back(i); size_t n = count_if(vec.begin(), vec.end(), is_even<int>); cout << "값이 짝수인 요소의 개수: " << n << endl; return 0;
binary_search()
bool comp(string s1, string s2) { return (s1 == s2); } int main(void) { vector<string> v = { "one", "two", "three" }; bool result; result = binary_search(v.begin(), v.end(), "two", comp); if (result == true) cout << "문자열 \"two\" 은 벡터 안에 있음." << endl; return 0;
for_each() 함수 void printEven(int n) { if (n % 2 == 0) cout << n << ' '; } int main(void) { vector<int> v = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; for_each(v.begin(), v.end(), printEven); cout << endl; return 0;
람다식
람다식의 정의
#include <iostream> using namespace std; int main() { auto sum = [](int x, int y) { return x + y; }; cout << sum(1, 2) << endl; cout << sum(10, 20) << endl; return 0; }
예제 bool is_greater_than_5(int value) { return (value > 5); } int main() vector<int> numbers{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; auto count = count_if(numbers.begin(), numbers.end(), is_greater_than_5); cout << "5보다 큰 정수들의 개수: " << count << endl; return 0;
Q & A