Читать книги » Книги » Компьютеры и Интернет » Программирование » C++17 STL Стандартная библиотека шаблонов - Яцек Галовиц

C++17 STL Стандартная библиотека шаблонов - Яцек Галовиц

Читать книгу C++17 STL Стандартная библиотека шаблонов - Яцек Галовиц, Яцек Галовиц . Жанр: Программирование.
C++17 STL Стандартная библиотека шаблонов - Яцек Галовиц
Название: C++17 STL Стандартная библиотека шаблонов
Дата добавления: 15 июль 2023
Количество просмотров: 1 473
(18+) Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних просмотр данного контента СТРОГО ЗАПРЕЩЕН! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту для удаления материала.
Читать онлайн

C++17 STL Стандартная библиотека шаблонов читать книгу онлайн

C++17 STL Стандартная библиотека шаблонов - читать онлайн , автор Яцек Галовиц

С++ — объектно-ориентированный язык программирования, без которого сегодня немыслима промышленная разработка ПО. В этой замечательной книге описана работа с контейнерами, алгоритмами, вспомогательными классами, лямбда-выражениями и другими интересными инструментами, которыми богат современный С++. Освоив материал, вы сможете коренным образом пересмотреть привычный подход к программированию.
Преимущество издания — в подробном описании стандартной библиотеки шаблонов С++, STL. Ее свежая версия была выпущена в 2017 году. В книге вы найдете более 90 максимально реалистичных примеров, которые демонстрируют всю мощь STL. Многие из них станут базовыми кирпичиками для решения более универсальных задач.
Вооружившись этой книгой, вы сможете эффективно использовать С++17 для создания высококачественного и высокопроизводительного ПО, применимого в различных отраслях.

1 ... 70 71 72 73 74 ... 121 ВПЕРЕД
Перейти на страницу:
meme>. Затем мы использовали конструкцию istream_iterator<pair<string, meme>>{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

 Очень легко вывести что-то на экран с помощью потоков вывода, поскольку в STL есть много полезных перегруженных версий оператора << для большинства простых типов. Таким образом, структуры данных, содержащие элементы подобных типов, можно легко вывести на экран, задействовав класс std::ostream_iterator, что мы довольно часто делали.

В данном примере мы сконцентрируемся на том, как это сделать для пользовательского типа и что еще можно сделать для управления выводом на экран с помощью выбора типа шаблона без необходимости писать при этом много кода на вызывающей стороне.

Как это делается

В этом примере мы поработаем с итератором std::ostream_iterator, объединив его с новым пользовательским классом, и взглянем на его возможности неявного преобразования, что может помочь при выводе данных на экран.

1. Сначала указываем, какие заголовочные файлы включить, а затем объявляем об использовании пространства имен std:

#include <iostream>

#include <vector>

#include <iterator>

#include <unordered_map>

#include <algorithm>

using namespace std;

2. Реализуем функцию преобразования, которая соотносит числа и строки. Она будет возвращать строку "one" для значения 1, "two" для значения 2 и т.д.:

string word_num(int i) {

3. Мы заполним ассоциативный массив, основанный на хешах, этими парами, чтобы получить к ним доступ позже:

  unordered_map<int, string> m {

    {1, "one"}, {2, "two"}, {3, "three"},

    {4, "four"}, {5, "five"}, //...

  };

4. Теперь можно передать в функцию find ассоциативного массива, основанного на хеше, аргумент i и вернуть то значение, которое она найдет. Если функция ничего не найдет — например, для заданного числа нет перевода, — то вернем строку "unknown":

  const auto match (m.find(i));

  if (match == end(m)) { return "unknown"; }

  return match->second;

};

5. Мы будем работать также со структурой bork. Она содержит только одно целое число и неявно создается на основе целого числа. Кроме того, она имеет функцию print, которая принимает ссылку на поток вывода и выводит строку "bork" столько раз, сколько указано в целочисленной переменной borks:

struct bork {

  int borks;

  bork(int i) : borks{i} {}

  void print(ostream& os) const {

    fill_n(ostream_iterator<string>{os, " "},

           borks, "bork!"s);

  }

};

6. Для использования функции bork::print перегрузим оператор << для объектов потока, чтобы они автоматически вызывали функцию bork::print, когда объекты типа bork попадают в поток вывода:

ostream& operator<<(ostream &os, const bork &b) {

  b.print(os);

  return os;

}

7. Теперь наконец можем начать реализовывать саму функцию main. Изначально просто создаем вектор, содержащий некоторые значения:

int main()

{

  const vector<int> v {1, 2, 3, 4, 5};

8. Для объектов типа ostream_iterator нужен параметр шаблона, который указывает, переменные какого типа они могут выводить. Если мы напишем ostream_iterator<T>, то в дальнейшем для вывода данных на экран будет применяться конструкция ostream& operator(ostream&, const T&). Именно это свойство мы и реализовали до типа bork. На сей раз просто выводим целые числа, поэтому специализация выглядит как ostream_iterator<int>. Для вывода информации на экран мы будем использовать поток cout, так что предоставим его в качестве параметра конструктора. Пройдем по вектору в цикле и присвоим каждый элемент i разыменованному итератору вывода. Именно так потоковые итераторы используются в алгоритмах STL.

  ostream_iterator<int> oit {cout};

  for (int i : v) { *oit = i; }

  cout << 'n';

9. Полученный от итератора результат нам подходит, но он выводит числа без каких-либо разделителей. Если мы хотим добавить пробелы-разделители между всеми выведенными элементами, то можем предоставить собственную строку с пробелами в качестве второго параметра конструктора итератора выводного потока. Данное действие позволит вывести строку "1, 2, 3, 4, 5, " вместо строки "12345". К сожалению, мы не

1 ... 70 71 72 73 74 ... 121 ВПЕРЕД
Перейти на страницу:
Комментарии (0)