[БЕЗ_ЗВУКА] Давайте рассмотрим задачу, когда нам нужно в определенном формате вывести данные, которые есть внутри нашей программы. Например, это могут быть какие-то имена колонок и, например, значения в этих колонках. И вы хотите, чтобы их было удобно читать. Давайте создадим вектор строк names и сохраним в него имена колонок, с которыми мы хотим в дальнейшем поработать. Допустим, это будет a, b и c. После этого создадим вектор значений. Пусть это будет вектор double values. И положим туда, например, 5, 0,01 и совсем какое-нибудь маленькое число, например, вот так. Замечательно. Давайте выведем их на экран так, как они сейчас есть, без всяких украшений. Воспользуемся циклом range-based for. И выведем по очереди имя каждой колонки. Сделаем перенос строки. И точно так же выведем наши значения, только будем итерироваться по массиву values. Давайте запустим нашу программу. Мы видим, что на экран вывелось a, b, c и соответствующие значения, при этом читать их очень неудобно. Если пятерка находится еще под a, то значение под b уже съехало немножко в сторону, и значение под c находится еще дальше нее. Для того чтобы решить такую задачу, в языке C++ есть файловые манипуляторы. Это манипуляторы, которые работают как-то с потоком и как-то изменяют его поведение. Например, вы можете сказать, что для следующего значения, которое я буду выводить в мой поток, зарезервируй определенное место и займи в этом месте столько места, сколько тебе нужно. Звучит немножко сложно, но давайте просто посмотрим, как оно работает, и я думаю, все станет ясно. Давайте для начала сделаем так, чтобы число, например, последнее, выводилось не в экспоненциальном формате, а, например, с десятичной точкой. Для этого мы должны сказать нашему потоку, что следующие числа вводи с фиксированной точностью. То есть для этого существует манипулятор fixed. Кстати, для того чтобы с ними работать, нам нужно подключить библиотеку iomanip. Давайте запустим наш код, видим, что действительно числа экспоненциальные, формат ушел. При этом появилось n знаков после запятой. В данном случае у каждого числа их получилось шесть. Давайте поработаем и с этим параметром, например, сделаем так, чтобы вводилось не шесть знаков после запятой, а только два. Для этого существует манипулятор setprecision. [ЗВУК] В него нам надо передать количество знаков после запятой, которые мы хотим видеть. Запускаем наш код, видим, что действительно стало вводиться два знака после запятой. Но при этом обращу ваше внимание на то, что читать данные по-прежнему не очень удобно. Что же нам с этим делать? Для того чтобы зарезервировать определенное место под переменную строчки, есть манипулятор setwidth. Давайте им воспользуемся. Положим его в поток setw. В него надо передать размер вашего кода, в который нужно положить переменную. Давайте сделаем его 10. Посмотрим, как изменится выхлоп нашей программы. Странно. Для пятерки место явно выделилось, при этом для остальных переменных — нет. Ключевая особенность данного манипулятора в том, что он сбрасывается после вывода переданного значения в него. То есть его надо выводить каждый раз, когда выводится какое-то значение. Давайте поправим наш код соответствующим образом. Запускаем. Видим, что да, действительно, все наши числа стали выводиться в определенном колоночном формате. Каждая из них стала занимать справа определенное место, а слева заполняется всё пробелами. Хорошо бы и колонки выводить ровно в таком же формате. Для этого мы можем точно так же использовать манипулятор setw в том месте, где мы выводим имена колонок. Запустим наш код, видим, что действительно колонки стали выводиться в определенном формате. Давайте для удобства напишем функцию, которая будет на вход принимать вектор имен и вектор значений, а также выводить их в определенном формате так, как нам удобно. Назовем ее для простоты просто Print. Передадим ей на вход вектор имен names, вектор значений, а также ширину столбца. Чуть-чуть не поместилось на экран, но я показываю, что эта переменная здесь есть. И давайте напишем код, который все это выведет на экран. В данном случае мы просто перенесем его выше. [ЗВУК] При этом 10 мы убираем, изменяем его на переменную width. [ЗВУК] Теперь позовем нашу функцию Print от имен и значений. Вызываем наш код. Да, совершенно верно — я забыл передать ширину колонки. Давайте сделаем это. Пусть она по умолчанию будет 10. Отлично. Видим, что наш код скомпилировался и значения вывелись. Для того чтобы, например, заполнить пространство между колонками определенным заполнителем, например, не пробелом, а точкой, нужно воспользоваться манипулятором setfill. Давайте сделаем это и передадим туда символ, которым мы хотим заполнять пустое пространство. Наш код скомпилировался, при этом мы видим, что здесь появились точки. Также иногда бывает полезно выводить числа, например, не справа, а слева. Для этого есть манипулятор left. Замечательно. Видим, что в выводе имена и значения колонок теперь выводятся слева. В данном примере мы с вами познакомились с тем, как выводить числа в различных форматах, а также строковые переменные, например, в поколоночном. Только что мы познакомились с потоковыми манипуляторами. Это такие объекты, которые позволяют производить некоторые манипуляции с объектами, которые мы выводим, представлять их в более удобочитаемом виде для нас. Напомню основные из них. setw позволяет задать ширину поля, в которое мы выводим объект. Также есть setprecision, который задает точность вывода вещественных чисел. setfill в основном используется как заполнитель для тех случаев, когда мы выделяем специальное поле для числа или строчки, а также left, которое позволяет выравнивать объекты слева, когда у нас остается дополнительное место в setw. Теперь мы умеем работать с потоками ввода и вывода. Мы умеем читать данные из файла, обрабатывать ситуации нестандартные, например, отсутствие файла, а также записывать данные файлы и делать запись с дозаписью, то есть не пересоздавать файл заново, а, например, записать в него сначала один текст, затем другой текст.