C++17 STL Стандартная библиотека шаблонов - Яцек Галовиц
Книгу C++17 STL Стандартная библиотека шаблонов - Яцек Галовиц читаем онлайн бесплатно полную версию! Чтобы начать читать не надо регистрации. Напомним, что читать онлайн вы можете не только на компьютере, но и на андроид (Android), iPhone и iPad. Приятного чтения!
Шрифт:
Интервал:
Закладка:
Некоторым людям нравится делать все расширения одинаковыми. Было бы полезно иметь возможность переименовать все файлы лишь одной командой. В то же время мы могли бы удалить все пробелы ' ' и заменить их, например, на '_'.
В данном примере мы реализуем такой инструмент и назовем его renamer. Он будет принимать диапазон входных шаблонов и их замен, это выглядит следующим образом:
$ renamer jpeg jpg JPEG jpg
В этом случае renamer рекурсивно проитерирует по текущему каталогу и выполнит поиск шаблонов jpeg и JPEG в именах всех файлов. Он заменит обе строки на jpg.
Как это делается
В этом примере мы реализуем инструмент, который рекурсивно просканирует все файлы внутри каталога и соотнесет их имена с заданным шаблоном. Все совпадения заменятся токенами, предоставленными пользователем, и найденные файлы будут переименованы соответствующим образом.
1. Сначала включим некоторые заголовочные файлы и объявим об использовании пространств имен std и filesystem:
#include <iostream>
#include <regex>
#include <vector>
#include <filesystem>
using namespace std;
using namespace filesystem;
2. Реализуем небольшую вспомогательную функцию, которая принимает путь к файлу в виде строки, а также диапазон пар для замены. Каждая пара для замены содержит шаблон и его замену. Проходя в цикле по диапазону, воспользуемся regex_replace, передавая ему входную строку и принимая преобразованную строку. После этого вернем полученную строку:
template <typename T>
static string replace(string s, const T &replacements)
{
for (const auto &[pattern, repl] : replacements) {
s = regex_replace(s, pattern, repl);
}
return s;
}
3. В функции main сначала проверим командную строку. Принимаем аргументы из нее попарно, поскольку нужно, чтобы шаблоны стояли рядом с их заменами. Первый элемент argv — всегда имя исполняемого файла. Это значит, что если пользователь предоставит хотя бы одну пару или больше, то argc должен быть нечетным и не меньше 3:
int main(int argc, char *argv[])
{
if (argc < 3 || argc % 2 != 1) {
cout << "Usage: " << argv[0]
<< " <pattern> <replacement> ...n";
return 1;
}
4. Как только мы убедились, что получили во входных значениях необходимые пары, заполним ими вектор:
vector<pair<regex, string>> patterns;
for (int i {1}; i < argc; i += 2) {
patterns.emplace_back(argv[i], argv[i + 1]);
}
5. Теперь можно проитерировать по файловой системе. Для простоты определим в качестве каталога, по которому нужно проитерировать, текущий каталог приложения. Затем возьмем только имена файлов без остальной части пути и преобразуем их соответственно списку шаблонов и замен, собранному ранее. Возьмем копию opath, назовем ее rpath и заменим часть имени файла новой:
for (const auto &entry :
recursive_directory_iterator{current_path()}) {
path opath {entry.path()};
string rname {replace(opath.filename().string(),
patterns)};
path rpath {opath};
rpath.replace_filename(rname);
6. Для всех файлов, чьи имена совпали с нашими шаблонами, выведем на экран строку, сигнализирующую о том, что мы переименовали их. Если полученное в результате переименования имя файла уже существует, то продолжать работу невозможно. Просто будем пропускать такие файлы. Вместо этого мы могли бы прикреплять какое-то число к пути или что-то еще с целью разрешить пересечение имен.
if (opath != rpath) {
cout << opath.c_str() << " --> "
<< rpath.filename().c_str() << 'n';
if (exists(rpath)) {
cout << "Error: Can't rename."
" Destination file exists.n";
} else {
rename(opath, rpath);
}
}
}
}
7. Компиляция и запуск программы для примера каталога дадут следующий результат. Я поместил несколько картинок в формате JPEG в каталог, но задал для них разные окончания: jpg, jpeg и JPEG. Затем выполнил программу, передав ей шаблоны jpeg и JPEG и выбрав замену jpg для них обоих. В результате получил каталог с одинаковыми расширениями файлов:
$ ls
birthday_party.jpeg holiday_in_dubai.jpg holiday_in_spain.jpg
trip_to_new_york.JPEG
$ ../renamer jpeg jpg JPEG jpg
/Users/tfc/pictures/birthday_party.jpeg --> birthday_party.jpg
/Users/tfc/pictures/trip_to_new_york.JPEG --> trip_to_new_york.jpg
$ ls
birthday_party.jpg holiday_in_dubai.jpg holiday_in_spain.jpg
trip_to_new_york.jpg
Создаем индикатор эксплуатации диска
Мы уже реализовали инструмент, который работает как ls в Linux/MacOS или dir в Windows, но, подобно этим утилитам, не выводит размер файлов в каталогах.
Чтобы получить эквивалент размера каталога, нужно зайти во все подкаталоги и суммировать размеры всех файлов, содержащихся в них.
В данном примере мы реализуем инструмент, который делает именно это. Инструмент можно запустить для любого каталога, он определит размер всех его записей.
Как это делается
В этом примере мы реализуем приложение, которое итерирует по каталогу и перечисляет размеры файлов для каждой записи. Это просто для обычных файлов, но если мы смотрим на запись каталога, которая сама по себе является каталогом, то нужно заглянуть в него и суммировать размеры всех файлов, хранящихся в нем.
1. Сначала включим все необходимые заголовочные файлы и объявим об использовании пространств имен std и filesystem:
#include <iostream>
#include <sstream>
#include <iomanip>
#include <numeric>
#include <filesystem>
using namespace std;
using namespace filesystem;
2. Затем реализуем вспомогательную функцию, которая принимает в качестве аргумента directory_entry и возвращает его размер в файловой системе. Это не каталог, мы просто вернем размер файла, вычисленный с помощью file_size:
static size_t entry_size(const directory_entry &entry)
{
if (!is_directory(entry)) { return file_size(entry); }
3. Если это каталог, то нужно проитерировать по всем его записям и подсчитать их размер. Мы будем вызывать вспомогательную функцию entry_size рекурсивно при повторной встрече с подкаталогами:
return accumulate(directory_iterator{entry}, {}, 0u,
Прочитали книгу? Предлагаем вам поделится своим отзывом от прочитанного(прослушанного)! Ваш отзыв будет полезен читателям, которые еще только собираются познакомиться с произведением.
Уважаемые читатели, слушатели и просто посетители нашей библиотеки! Просим Вас придерживаться определенных правил при комментировании литературных произведений.
- 1. Просьба отказаться от дискриминационных высказываний. Мы защищаем право наших читателей свободно выражать свою точку зрения. Вместе с тем мы не терпим агрессии. На сайте запрещено оставлять комментарий, который содержит унизительные высказывания или призывы к насилию по отношению к отдельным лицам или группам людей на основании их расы, этнического происхождения, вероисповедания, недееспособности, пола, возраста, статуса ветерана, касты или сексуальной ориентации.
- 2. Просьба отказаться от оскорблений, угроз и запугиваний.
- 3. Просьба отказаться от нецензурной лексики.
- 4. Просьба вести себя максимально корректно как по отношению к авторам, так и по отношению к другим читателям и их комментариям.
Надеемся на Ваше понимание и благоразумие. С уважением, администратор knigkindom.ru.
Оставить комментарий
-
Р.Д.У.22 август 02:17
...мне тоже понравился этот русский вестерн. И озвучено неплохо. Советую....
Силантьев Вадим – Засада
-
Гость Любовь21 август 20:01
Прочитала залпом.... интересный сюжет, история захватывает, плакала вместе с героями. спасибо автору за интересное...
Вернуть жену. Без права на прощение? - Ира Орлова
-
Ма21 август 02:06
Роман хороший, но очень топорный и поэтому скучноватый, все как будто поверхностно, акцент на работе героев - киллер и главбух, а...
Гектор - Ольга Дашкова
