Не из лекции

Заголовка <iomanip> в материалах первого занятия нет вовсе: ни в лонгриде, ни в коде. Страница написана «на вырост» — материал верный и в задачах пригодится, но на контрольные вопросы курса по L01 он не отвечает. Из манипуляторов на занятии встречался только std::boolalpha — см. Потоки ввода и вывода.

Манипуляторы из <iomanip> управляют тем, как поток печатает значение: ширина поля, символ-заполнитель, количество знаков после запятой.

#include <iomanip>
#include <iostream>
 
int main() {
  std::cout << std::setfill('0') << std::setw(2) << 7 << '\n';  // 07
  return 0;
}

Главное правило: одни манипуляторы липкие, другие нет

std::setw действует ровно на один следующий вывод и сбрасывается:

std::cout << std::setw(4) << 1 << 2 << '\n';   // "   12", а не "   1   2"

Все остальные — setfill, setprecision, fixed, left, right, boolalpha — липкие: заданы один раз и действуют до отмены.

std::cout << std::setfill('0');                 // теперь всегда нули
std::cout << std::setw(2) << 5 << ':'
          << std::setw(2) << 7 << '\n';         // 05:07 — setw пишем дважды

Это первая причина, почему форматированный вывод «съезжает»: setw забыли повторить.

Числа с дробной частью

double value = 3.14159;
 
std::cout << std::setprecision(3) << value << '\n';               // 3.14
std::cout << std::fixed << std::setprecision(3) << value << '\n'; // 3.142

Без std::fixed аргумент setprecision означает количество значащих цифр, вместе с std::fixed — количество знаков после точки. Разница проявляется на числах вроде 0.00123, и её регулярно путают.

Оба манипулятора липкие: выставив std::fixed, вы меняете формат всего дальнейшего вывода вещественных чисел.

Выравнивание

std::cout << std::left  << std::setw(10) << "имя" << "|\n";   // имя       |
std::cout << std::right << std::setw(10) << "имя" << "|\n";   //        имя|

По умолчанию числа и строки прижимаются вправо.

Тонкости

  • setw не обрезает: если значение длиннее ширины, оно печатается целиком, таблица разъезжается.
  • setfill принимает char: '0', а не "0".
  • Ширину и заполнитель задают до значения, а не после — манипулятор влияет на то, что идёт следом.
  • <iomanip> нужно подключать отдельно от <iostream>, см. Подключение заголовков.

Частые ошибки

  • Один setw на несколько значений — сработает только на первом.
  • setprecision без fixed там, где нужны именно знаки после точки.
  • Попытка выровнять вывод пробелами вручную вместо setw — ломается на числах другой длины.