스트림(stream)(4) 반복문 없이 벡터 입/출력 (std::vector I/O without loop statement)
스트림과 반복자(iterator)를 활용하면 for
/while
문 없이 std::vector
를 입/출력 할 수 있다. 최종 코드
1. std::istream_iterator
코드부터 보자면 다음과 같다
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
int main() {
std::istream_iterator<int> cin_iter(std::cin);
std::istream_iterator<int> eos;
std::vector<int> num;
std::copy(cin_iter, eos, std::back_inserter(num));
for(auto it: num) {
std::cout << it << std::endl;
}
return 0;
}
1-1 <iterator>
내부에 정의된 std::istream_iterator
std::istream
클래스는 iterator를 자식으로 두고 있지 않다. 다른 STL 컨테이너 클래스처럼 std::cin.begin()
으로 iterator를 만들 수 없다는 뜻이다.
그래서 std::istream
, 위 코드에서는 std::cin
의 iterator를 사용하기 위해서는 <iterator>
헤더를 include해야 하고, 헤더에 선언된 std::istream_iterator
로 std::cin
의 iterator를 생성해야한다. std::istream_iterator
의 기본 생성자는 end-of-stream
이다. 스트림의 끝을 나타내는 것이다.
1-2 std::istream_iterator
와 std::cin
의 end-of-stream
차이
std::cin
의 >>
연산과 달리, std::istream_iterator
는 스페이스나 엔터키로 스트림 입력을 끊지 않는다. 위 코드에서는 ^D
(ctrl+D
)로 EOF
플래그를 입력해 스트림의 끝을 알린다. 그래서 위 사진에 ^D가 다음 줄에 있는 것이다. EOF
또한 입력이므로 입력 내용이랑 구분(위 경우에서는 스페이스로 간격을 주고)해 입력해야한다.
1-3 std::copy
std::copy()
는 <algorithm>
헤더에, 선언된 함수이다.
std::copy()
는 3가지 parameter가 들어간다. 각각 입력 인스턴스의 시작 iterator와 끝 iterator, 출력 인스턴스의 시작 iterator이다.
std::vector<int> copy_src = {1, 3, 5};
std::vector<int> copy_dst;
std::copy(copy_src.begin(), copy_src.end(), copy_dst.begin());
// copy_dst에 1, 3, 5가 복사됨
1-4 std::back_inserter
std::back_inserter()
는 <iterator>
헤더에 선언된 함수이다.
std::back_inserter()
는 컨테이너(이 경우에서는 std::vector
)를 argument로 가지고, std::back_insert_iterator
를 return한다. std::back_insert_iterator
는 auto
와 비슷하게 대응되는 인스턴스의 클래스에 맞게 변화한다.(자세한 내용은 여기)
결국 std::copy(cin_iter, eos, std::back_inserter(num));
은 std::cin
의 iterator부터 end-of-stream
iterator까지를 입력으로 num
의 back_insert_iterator
에 복사하는 동작이다.
2. std::ostream_iterator
위 내용을 이해했다면 std::ostream_iterator
는 이해하기 쉽다.
#include <iostream>
#include <vector>
#include <iterator>
int main() {
std::vector<int> num = {1, 3, 5, 7};
std::ostream_iterator<int> cout_iter(std::cout);
std::copy(num.begin(), num.end(), cout_iter);
return 0;
}
여기서 std::istream_iterator
가 구분자(delimiter)를 std::cin
을 따라 스페이스바로 가져간 것처럼, std::ostream_iterator
또한 std::cout
처럼 빈칸 없이 출력된다. 이때 다음과 같이 선언하면 구분자를 줄 수 있다.
std::ostream_iterator<int> cout_iter(std::cout, ", ")
3. 합쳐서
두 stream_iterator
를 합치면 다음과 같은 코드가 나온다.
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
int main() {
std::vector<int> num;
std::istream_iterator<int> cin_iter(std::cin);
std::istream_iterator<int> eos;
std::ostream_iterator<int> cout_iter(std::cout, " ");
std::copy(cin_iter, eos, std::back_inserter(num));
std::copy(num.begin(), num.end(), cout_iter);
return 0;
}
Leave a comment