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

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

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

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

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

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

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

  for (const auto &[ext, stats] : ext_stats(dir)) {

    const auto &[accum_size, count] = stats;

    cout << setw(15) << left << ext << ": "

         << setw(4) << right << count

         << " items, avg size "

         << setw(4) << size_string(accum_size / count)

         << 'n';

  }

}

10. Компиляция и запуск программы дадут следующий результат. Я предоставил ей в качестве аргумента командной строки каталог, содержащий офлайн-справку по С++.

$ ./file_type ~/Documents/cpp_reference/

.css   :    2 items, avg size  41K

.gif   :    7 items, avg size 902B

.html  : 4355 items, avg size  38K

.js    :    3 items, avg size   4K

.php   :    1 items, avg size 739B

.png   :   34 items, avg size   2K

.svg   :   53 items, avg size   6K

.ttf   :    2 items, avg size 421K 

Инструмент для уменьшения размера папки путем замены дубликатов символьными ссылками

Существует множество инструментов, сжимающих данные разными способами. Наиболее известными примерами таких алгоритмов/форматов являются ZIP и RAR. Подобные инструменты уменьшают размер файлов, снижая их внутреннюю избыточность.

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

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

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

 

 Убедитесь, что создали резервные копии системных данных. Мы будем работать с функциями STL, которые удаляют файлы. Неверно указанный путь для такой программы может привести к тому, что программа жадно удалит нежелательным способом слишком много файлов.

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

#include <iostream>

#include <fstream>

#include <unordered_map>

#include <filesystem>

using namespace std;

using namespace filesystem;

2. Чтобы определить, какие файлы являются дубликатами друг друга, создадим ассоциативный массив, в котором соотносятся хеши файлов и путь к первому файлу, из которого был получен этот хеш. Для получения таких хешей следует использовать популярный алгоритм, такой как MD5 или SHA. В целях сохранения данного примера чистым и простым просто считаем весь файл в строку, а затем задействуем объект хеш-функции, уже применяемый unordered_map для подсчета хешей строк:

static size_t hash_from_path(const path &p)

{

  ifstream is {p.c_str(),

               ios::in | ios::binary};

  if (!is) { throw errno; }

  string s;

  is.seekg(0, ios::end);

  s.reserve(is.tellg());

  is.seekg(0, ios::beg);

  s.assign(istreambuf_iterator<char>{is}, {});

  return hash<string>{}(s);

}

3. Затем реализуем функцию, которая создает такой ассоциативный массив, основанный на хешах, и удаляет дубликаты. Она рекурсивно итерирует по каталогу и его подкаталогам:

static size_t reduce_dupes(const path &dir)

{

  unordered_map<size_t, path> m; size_t count {0};

  for (const auto &entry :

     recursive_directory_iterator{dir}) {

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

    const path p {entry.path()};

    if (is_directory(p)) { continue; }

    const auto &[it, success] =

      m.try_emplace(hash_from_path(p), p);

5. Задействуя значения, возвращаемые try_emplace, мы можем сказать пользователю, что мгновение назад вставили файл, поскольку встретили этот хеш в первый раз. Если мы нашли дубликат, то сообщаем пользователю о том, что второй файл является дубликатом, и удаляем его. После удаления создаем символьную ссылку, которая заменяет дубликат.

    if (!success) {

      cout << "Removed " << p.c_str()

           << " because it is a duplicate of "

           << it->second.c_str() << 'n';

      remove(p);

      create_symlink(absolute(it->second), p);

      ++count;

    }

6. После перебора в файловой системе возвращаем количество файлов, которые мы удалили и заменили файловыми ссылками.

  }

  return count;

}

7. В функции main убеждаемся, что пользователь передал каталог в командной строке и что этот каталог существует:

int main(int argc, char *argv[])

{

  if (argc != 2) {

    cout << "Usage: " << argv[0] << " <path>n";

    return 1;

  }

  path dir {argv[1]};

  if (!exists(dir)) {

    cout << "Path " << dir << " does not exist.n";

    return 1;

  }

8. Единственное, что нам осталось сделать, — вызвать функцию reduce_dupes для этого каталога и вывести на экран информацию о том, сколько файлов мы удалили:

  const size_t dupes {reduce_dupes(dir)};

  cout << "Removed " << dupes << " duplicates.n";

}

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

$ du -sh dupe_dir

1.1M dupe_dir

$ ./dupe_compress dupe_dir

Removed dupe_dir/dir2/bar.jpg because it is a duplicate of

dupe_dir/dir1/bar.jpg

Removed dupe_dir/dir2/base10.png because it is a duplicate of

dupe_dir/dir1/base10.png

Removed dupe_dir/dir2/baz.jpeg because it is a

Перейти на страницу:
Комментарии (0)