STL 반복자
2025. 3. 28. 08:54ㆍProgramming Languages/C++
8.3 STL 반복자
반복자(Iterator)는 컨테이너의 요소에 접근하고 순회하는 통일된 방법을 제공합니다.
8.3.1 반복자 개념과 카테고리
STL은 다음과 같은 반복자 카테고리를 정의합니다:
- 입력 반복자(Input Iterator): 한 번에 한 방향으로만 이동 가능, 읽기 전용
- 출력 반복자(Output Iterator): 한 번에 한 방향으로만 이동 가능, 쓰기 전용
- 순방향 반복자(Forward Iterator): 한 방향으로 여러 번 이동 가능
- 양방향 반복자(Bidirectional Iterator): 양방향으로 이동 가능
- 임의 접근 반복자(Random Access Iterator): 임의의 위치로 바로 이동 가능
#include <iostream>
#include <vector>
#include <list>
#include <map>
#include <iterator> // 반복자 도구
#include <algorithm> // for_each
int main() {
// 컨테이너 생성
std::vector<int> vec = {1, 2, 3, 4, 5}; // 임의 접근 반복자 제공
std::list<int> lst = {10, 20, 30, 40, 50}; // 양방향 반복자 제공
std::map<std::string, int> mp = {{"one", 1}, {"two", 2}, {"three", 3}}; // 양방향 반복자 제공
// 기본 반복자 사용
std::cout << "벡터 요소: ";
for (std::vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
// auto를 사용한 간결한 방법 (C++11)
std::cout << "리스트 요소: ";
for (auto it = lst.begin(); it != lst.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
// 맵 반복자 (pair 반환)
std::cout << "맵 요소:" << std::endl;
for (auto it = mp.begin(); it != mp.end(); ++it) {
std::cout << " " << it->first << ": " << it->second << std::endl;
}
// 역방향 반복자
std::cout << "벡터 요소 (역순): ";
for (auto rit = vec.rbegin(); rit != vec.rend(); ++rit) {
std::cout << *rit << " ";
}
std::cout << std::endl;
// 상수 반복자 (읽기 전용)
std::cout << "리스트 요소 (상수 반복자): ";
for (std::list<int>::const_iterator it = lst.cbegin(); it != lst.cend(); ++it) {
// *it = 100; // 오류: 상수 반복자는 수정 불가
std::cout << *it << " ";
}
std::cout << std::endl;
// 반복자로 값 수정
for (auto it = vec.begin(); it != vec.end(); ++it) {
*it *= 2; // 각 요소를 2배로
}
// 벡터의 임의 접근 반복자 기능
auto it = vec.begin();
std::cout << "세 번째 요소: " << it[2] << std::endl; // 배열처럼 접근
it += 2; // 두 단계 전진
std::cout << "현재 요소: " << *it << std::endl;
it -= 1; // 한 단계 후퇴
std::cout << "현재 요소: " << *it << std::endl;
// 반복자 간 거리
auto first = vec.begin();
auto last = vec.end();
std::cout << "벡터 요소 수: " << std::distance(first, last) << std::endl;
// for_each 알고리즘과 반복자
std::cout << "맵 요소 (for_each 사용): " << std::endl;
std::for_each(mp.begin(), mp.end(), [](const auto& pair) {
std::cout << " " << pair.first << ": " << pair.second << std::endl;
});
// 스트림 반복자 사용
std::cout << "숫자 입력 (Ctrl+D로 종료): ";
std::istream_iterator<int> input_iter(std::cin);
std::istream_iterator<int> eos; // 끝 반복자
std::vector<int> input_numbers;
std::copy(input_iter, eos, std::back_inserter(input_numbers));
std::cout << "입력한 숫자: ";
std::copy(input_numbers.begin(), input_numbers.end(),
std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
return 0;
}
8.3.2 특수 반복자
삽입 반복자(Insert Iterators)
#include <iostream>
#include <vector>
#include <list>
#include <set>
#include <iterator>
#include <algorithm>
int main() {
std::vector<int> source = {1, 2, 3, 4, 5};
// back_inserter: push_back을 사용하여 뒤에 삽입
std::vector<int> dest1;
std::copy(source.begin(), source.end(), std::back_inserter(dest1));
std::cout << "back_inserter 결과: ";
for (const auto& elem : dest1) {
std::cout << elem << " ";
}
std::cout << std::endl;
// front_inserter: push_front를 사용하여 앞에 삽입 (리스트와 같은 컨테이너에만 사용 가능)
std::list<int> dest2;
std::copy(source.begin(), source.end(), std::front_inserter(dest2));
std::cout << "front_inserter 결과: ";
for (const auto& elem : dest2) {
std::cout << elem << " "; // 역순으로 출력됨: 5 4 3 2 1
}
std::cout << std::endl;
// inserter: 지정된 위치에 삽입
std::vector<int> dest3 = {10, 20, 30};
std::copy(source.begin(), source.end(), std::inserter(dest3, dest3.begin() + 1));
std::cout << "inserter 결과: ";
for (const auto& elem : dest3) {
std::cout << elem << " "; // 10 1 2 3 4 5 20 30
}
std::cout << std::endl;
// set에 삽입
std::set<int> dest4;
std::copy(source.begin(), source.end(), std::inserter(dest4, dest4.end()));
std::cout << "set inserter 결과: ";
for (const auto& elem : dest4) {
std::cout << elem << " ";
}
std::cout << std::endl;
return 0;
}
스트림 반복자(Stream Iterators)
#include <iostream>
#include <fstream>
#include <iterator>
#include <vector>
#include <algorithm>
#include <string>
int main() {
// 파일에서 정수 읽기
std::ifstream in_file("numbers.txt");
if (!in_file) {
std::cerr << "Could not open numbers.txt" << std::endl;
return 1;
}
std::istream_iterator<int> file_iter(in_file);
std::istream_iterator<int> eof;
std::vector<int> numbers(file_iter, eof);
// 읽은 숫자 출력
std::cout << "파일에서 읽은 숫자: ";
std::copy(numbers.begin(), numbers.end(),
std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
// 표준 입력에서 문자열 읽기
std::cout << "몇 개의 단어를 입력하세요 (Ctrl+D로 종료): ";
std::istream_iterator<std::string> word_iter(std::cin);
std::istream_iterator<std::string> word_eof;
std::vector<std::string> words(word_iter, word_eof);
// 읽은 단어 정렬 후 출력
std::sort(words.begin(), words.end());
std::cout << "정렬된 단어: ";
std::copy(words.begin(), words.end(),
std::ostream_iterator<std::string>(std::cout, " "));
std::cout << std::endl;
// 파일에 숫자 쓰기
std::ofstream out_file("sorted_numbers.txt");
if (!out_file) {
std::cerr << "Could not create sorted_numbers.txt" << std::endl;
return 1;
}
std::sort(numbers.begin(), numbers.end());
std::copy(numbers.begin(), numbers.end(),
std::ostream_iterator<int>(out_file, "\n"));
std::cout << "정렬된 숫자를 sorted_numbers.txt에 저장했습니다." << std::endl;
return 0;
}
역방향 반복자(Reverse Iterators)
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
// 정방향 반복자로 출력
std::cout << "정방향: ";
for (auto it = vec.begin(); it != vec.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
// 역방향 반복자로 출력
std::cout << "역방향: ";
for (auto rit = vec.rbegin(); rit != vec.rend(); ++rit) {
std::cout << *rit << " ";
}
std::cout << std::endl;
// 알고리즘에서 역방향 반복자 사용
std::vector<int> dest(vec.size());
std::copy(vec.rbegin(), vec.rend(), dest.begin());
std::cout << "역순으로 복사: ";
for (const auto& elem : dest) {
std::cout << elem << " ";
}
std::cout << std::endl;
// 반복자 변환
auto it = vec.begin() + 2; // 세 번째 요소 가리킴
std::cout << "it가 가리키는 값: " << *it << std::endl; // 3
// 정방향 -> 역방향
auto rit = std::vector<int>::reverse_iterator(it);
std::cout << "rit가 가리키는 값: " << *rit << std::endl; // 2 (주의: 이전 요소)
// 역방향 -> 정방향
auto it2 = rit.base();
std::cout << "it2가 가리키는 값: " << *it2 << std::endl; // 3
return 0;
}
'Programming Languages > C++' 카테고리의 다른 글
| 함수 객체와 람다 표현식 (0) | 2025.03.28 |
|---|---|
| STL 알고리즘 (0) | 2025.03.28 |
| STL 컨테이너 (0) | 2025.03.28 |
| STL (Standard Template Library) (0) | 2025.03.28 |
| 챕터7. 실습 문제 (0) | 2025.03.28 |