- •Ооп: Лекция 7. Стандартная библиотека шаблонов ч.1
- •Адаптеры stl-контейнеров
- •Категории итераторов
- •Итераторы stl-контейнеров
- •Реверс-итератор можно преобразовать в обычный итератор через метод base().
- •Примеры алгоритмов и итераторов
- •Недействительные итераторы
- •При удалении все элементы, стоящие правее, сдвигаются на одну ячейку влево. При этом, итератор, по-прежнему указывает на ту же самую позицию:
- •Затем, итератор инкрементируется, указывая уже на следующую позицию:
- •При работе с другими контейнерами также следует соблюдать осторожность, и задумываться о ситуациях, при которых могут появляться недействительные итераторы:
- •Алгоритмы стандартной библиотеки
- •Пример использования изученных элементов stl
- •Полные примеры из лекции
Пример использования изученных элементов stl
Закрепим изученный материал при помощи полного примера программы. Условие задачи гласит:
на вход программы в файле “cities.txt” подаются строки с названиями городов;
строки подаются в произвольном порядке и могут повторяться;
программа должна считать данный файл и вывести в файл “results.txt” уникальные названия городов, при этом список городов должен быть упорядочен по алфавиту.
В качестве входных данных подается следующий тестовый файл:
cities.txt
Paris
Kyiv
London
Warsaw
London
Berlin
Paris
Amsterdam
Oslo
Rome
Berlin
Bratislava
Ниже представлена реализация данной программы с применением контейнеров, итераторов и алгоритмов стандартной библиотеки шаблонов.
cities.cpp:
#include <fstream>
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <string>
int main ()
{
// Открываем входной файл с целью чтения
std::ifstream fInput( "cities.txt", std::ios_base::in );
if ( ! fInput.is_open() )
{
// Не удалось открыть входной файл
std::cout << "Failed to open 'cities.txt'" << std::endl;
return -1;
}
// Открываем выходной файл с целью записи
std::ofstream fOutput( "results.txt", std::ios_base::out );
if ( !fOutput.is_open() )
{
// Не удалось открыть выходной файл
std::cout << "Failed to open 'results.txt'" << std::endl;
return -1;
}
// Названия городов будут храниться в векторе строк
std::vector< std::string > cities;
// Считываем названия городов из входного файла в вектор.
// Используем:
// - алгоритм std::copy
// - входной потоковый итератор std::istream_iterator для файлового потока
// - выходной итератор вставки std::back_insert_iterator для вектора
std::copy(
std::istream_iterator< std::string >( fInput ),
std::istream_iterator< std::string >(),
std::back_inserter( cities )
);
// Упорядочиваем названия городов по алфавиту
std::sort( cities.begin(), cities.end() );
// Перемещаем неповторяющиеся названия городов в начальную часть вектора.
// Результирующий итератор - граница уникальных названий городов в результате
auto itUniqueEnd = std::unique( cities.begin(), cities.end() );
// Копируем неповторяющийся отсортированный набор названий городов в выходной файл
// Используем:
// - алгоритм std::copy
// - выходной потоковый итератор std::ostream_iterator с файловым потоком
std::copy(
cities.begin(),
itUniqueEnd,
std::ostream_iterator< std::string >( fOutput, "\n" )
);
// Файлы закрываются автоматически
// Данные в памяти очищаются автоматически
}
В результате выполнения программы создается следующий выходной файл:
results.txt
Amsterdam
Berlin
Bratislava
Kyiv
London
Oslo
Paris
Rome
Warsaw
Полные примеры из лекции
https://github.com/zaychenko-sergei/oop-samples/tree/master/lec7
Выводы
В данной лекции были показаны современные приемы обобщенного программирования с применением стандартной библиотеки шаблонов - контейнеров, итераторов и алгоритмов. Приведено сравнение свойств и возможностей основных контейнеров - векторов, связных списков и деков. Рассмотрены особенности адаптеров контейнеров - стеки, очереди и очереди с приоритетами. Показана роль и различия в возможностях итераторов различной категории. Пояснена связь между итераторами и контейнерами. Наконец, проведен подробный обзор алгоритмов стандартной библиотеки - базовых строительных блоков любой программы, использующей контейнеры.
