8. На этом все. Нам нужна небольшая база данных интернет-мемов, так что заполним текстовый файл некоторыми примерами:
"Doge" "Very Shiba Inu. so dog. much funny. wow." 2013
"Pepe" "Anthropomorphic frog" 2016
"Gabe" "Musical dog on maximum borkdrive" 2016
"Honey Badger" "Crazy nastyass honey badger" 2011
"Dramatic Chipmunk" "Chipmunk with a very dramatic look" 2007
9. Компиляция и запуск программы с базой данных, содержащей примеры мемов, дадут следующий результат:
$ cat memes.txt | ./filling_containers
Doge : Very Shiba Inu. so dog. much funny. wow., 2013
Dramatic Chipmunk : Chipmunk with a very dramatic look, 2007
Gabe : Musical dog on maximum borkdrive, 2016
Honey Badger : Crazy nastyass honey badger, 2011
Pepe : Anthropomorphic frog, 2016
Как это работает
В данном примере можно отметить три интересные детали. Первая заключается в том, что на основе данных последовательного символьного потока ввода мы заполняли не вектор или список, а более сложный контейнер std::map
accumulate
, который определяет размер самой длинной строки.Начнем с работы с ассоциативным массивом. Наша структура meme
std::pair
, имеющий разные типы для ключа и значения. Именно это мы и сделали. Сначала реализовали оператор потока >>
для структуры meme
, а затем сделали то же самое для типа pair
. Затем мы использовали конструкцию istream_iterator>{cin}
, чтобы получить такие элементы из стандартного потока ввода и передать их в ассоциативный массив с помощью inserter(m, end(m))
.При десериализации элементов типа meme
"Name with spaces" "Description with spaces" 123
.При работе со строками, заключенными в кавычки как на входе, так и на выходе, поможет std::quoted
s
, то при выводе ее с помощью cout << quoted(s)
она будет заключена в кавычки. В случае десериализации строки из потока, например используя cin >> quoted(s)
, мы считаем следующий символ кавычек, заполним строку символами, стоящими после него, и будем делать это до тех пор, пока не увидим следующий символ кавычек, независимо от количества встреченных пробелов.Последний необычный момент заключается в том, как мы передали функцию max_func
accumulate
:auto max_func ([](size_t old_max, const auto &b) {
return max(old_max, b.first.length());
});
size_t width {accumulate(begin(m), end(m), 0u, max_func)};
Похоже, что функция max_func
size_t
и еще один аргумент с автоматическим типом, который оказывается элементом типа pair
, взятым из ассоциативного массива. На первый взгляд все выглядит очень странно, поскольку большинство бинарных функций сжатия принимают аргументы идентичных типов, а затем объединяют их с помощью некой операции, как, например, это делает std::plus
. В нашем случае все выглядит по-другому, поскольку мы не объединяем сами пары. Мы только получаем длину каждой строки, представляющей собой ключ, для каждой пары, size_t
с помощью функции max
.В вызове accumulate
max_func
получает значение 0u
, изначально предоставленное нами в качестве левого аргумента, и ссылку на первый элемент типа pair
с правой стороны. Это дает возвращаемое значение max(0u, string_length)
, которое станет левым аргументом для Выводим любые данные на экран с помощью итераторов std::ostream