Адаптер istream_iterator
std::istream
(который может представлять собой стандартный поток ввода или файлы) и будет пытаться преобразовывать полученные данные в соответствии с параметром шаблона. В этом примере мы использовали конструкцию std::istream_iterator(std::cin)
, получающую из потока ввода целые числа.Как правило, мы не знаем длину потока. Это оставляет открытым вопрос: куда указывает
std::ostream_iterator
Адаптер ostream_iterator
istream_iterator
, но работает по обратному принципу: не принимает токены ,
" или символ перехода на новую строку. Реализуем алгоритмы с помощью итераторов
Итераторы обычно итерируют,
++it
) и возвращать это значение при разыменовании (*it
).В данном разделе мы рассмотрим этот принцип, реализовав функцию, выводящую на экран последовательность чисел Фибоначчи с помощью итераторов. Такая функция рекурсивно определяется следующим образом: F(n) = F(n-1)+F(n-2)
F(0) = 0
и F(1) = 1
. Это приводит к появлению такой последовательности чисел:□ F(0) = 0;
□ F(1) = 1;
□ F(2) = F(1)+F(0) = 1;
□ F(3) = F(2)+F(1) = 2;
□ F(4) = F(3)+F(2) = 3;
□ F(5) = F(4)+F(3) = 5;
□ F(6) = F(5)+F(4) = 8;
□ ... и т.д.
Если мы реализуем это в форме вызываемой функции, которая возвращает значение Фибоначчи для любого числа n, то получим рекурсивную функцию, вызывающую саму себя, или цикл. Такой результат приемлем, но что, если мы напишем программу, принимающую числа Фибоначчи по некоему шаблону одно за другим? У нас есть два варианта: либо выполнять все рекурсивные вызовы для каждого числа Фибоначчи (это, по сути, растрата вычислительного времени), либо сохранять два последних числа во временных переменных и использовать их для вычисления следующего. Во втором случае придется
size_t a {0};
size_t b {1};
for (size_t i {0}; i < N; ++i) {
const size_t old_b {b};
b += a;
a = old_b;
// сделаем что-нибудь с b, текущим числом Фибоначчи
}
Итераторы позволяют решить задачу оригинальным способом. Можно обернуть шаги, которые нужно сделать в реализации, основанной на цикле функции Фибоначчи, в префиксный оператор ++
Как это делается
В этом примере мы сконцентрируемся на реализации итератора, который генерирует числа на основе последовательности чисел Фибоначчи.
1. Чтобы иметь возможность вывести на экран числа Фибоначчи, включим соответствующий заголовочный файл:
#include
2. Определим итератор Фибоначчи, fibit
i
, в котором будет сохраняться индекс позиции в последовательности Фибоначчи, а также члены a
и b
, в которых будут храниться два последних значения Фибоначчи. При вызове конструктора по умолчанию итератор Фибоначчи инициализируется значениями F(0)
.class fibit
{
size_t i {0};
size_t a {0};
size_t b {1};
3. Далее определим стандартный конструктор и конструктор, который позволит инициализировать итератор любым этапом вычисления чисел Фибоначчи:
public:
fibit() = default;
explicit fibit(size_t i_)
: i{i_}
{}
4. Разыменование итератора (*it
size_t operator*() const { return b; }