Форматированный ввод и вывод
Форматная строка — это шаблон
printf и scanf работают по форматной строке — шаблону, где обычный текст перемешан
со спецификаторами %.
Аналогия. Форматная строка — бланк заказа в кафе: «Кофе: ___, размер: ___». Пустые поля (
%) заполняются значениями, а слова и запятые остаются как есть.
printf("Студент №%d получил %d баллов\n", 12, 5);
/* ^ поле-число ^ поле-число */
Порядок важен: первый % берёт первое значение, второй — второе.
Полный вид спецификатора вывода
%[флаги][ширина][.точность][длина]спецификатор
Все части, кроме последней, необязательны. Разберём %08.3f:
| Часть | Значение | В примере |
|---|---|---|
| флаги | дополнительное оформление | 0 — дополнить нулями |
| ширина | минимальное число символов | 8 — всего 8 позиций |
| точность | знаков после точки | .3 — три знака |
| спецификатор | тип значения | f — дробное число |
Для числа 3.14159 результат — 0003.142.
Флаги
| Флаг | Что делает | Пример | Результат |
|---|---|---|---|
- | выравнивание по левому краю | %-6d, 42 | 42 |
+ | показывать знак + | %+d, 42 | +42 |
0 | дополнить нулями | %05d, 42 | 00042 |
# | показывать основание | %#x, 255 | 0xff |
| пробел | пробел вместо + | % d, 42 | 42 |
Ширина и точность
printf("|%d|\n", 42); /* |42| */
printf("|%5d|\n", 42); /* | 42| */
printf("|%-5d|\n", 42); /* |42 | */
printf("|%05d|\n", 42); /* |00042| */
printf("%.2f\n", 3.14159); /* 3.14 */
printf("%8.2f\n", 3.14159); /* 3.14 */
printf("%.0f\n", 2.6); /* 3 — округление до целого */
- ширина — сколько минимум позиций займёт значение (если число короче, добавляются пробелы);
- точность для дробных — сколько знаков после точки (последний знак округляется).
Выравнивание «таблицей» без циклов
Даже без циклов можно напечатать ровные колонки: укажите ширину поля в каждой строке.
#include <stdio.h>
int main(void)
{
double a = 199.9, b = 45.0, c = 1234.5;
printf("№ Цена\n"); /* обычный текст без спецификаторов */
printf("%-8d%10.2f\n", 1, a);
printf("%-8d%10.2f\n", 2, b);
printf("%-8d%10.2f\n", 3, c);
return 0;
}
№ Цена
1 199.90
2 45.00
3 1234.50
%-8d — целое в поле шириной 8 по левому краю, %10.2f — число в поле шириной 10
с двумя знаками после точки. Текст заголовка печатается как обычные символы.
Спецификаторы длины: не перепутать тип
Длина указывается перед спецификатором и должна совпадать с типом переменной:
| Тип | Ввод (scanf) | Вывод (printf) |
|---|---|---|
int | %d | %d |
long long | %lld | %lld |
float | %f | %f |
double | %lf | %f |
Запомните разницу: в scanf для double нужен %lf, а в printf — %f
(там l не требуется, потому что float уже повышен до double).
Форматированный ввод
scanf пропускает пробельные символы (пробелы, табы, переводы строк) перед числами,
поэтому данные можно вводить как угодно:
int a, b;
double x;
scanf("%d %d %lf", &a, &b, &x);
Ширину поля можно ограничить — удобно, чтобы не «съесть» лишние символы:
int day, month;
scanf("%2d%2d", &day, &month); /* ввод 1209 → 12 и 9 */
Спецификатор %c — исключение: он читает любой символ, включая пробел и перевод строки.
Поэтому перед %c ставят пробел:
int n;
char c;
scanf("%d", &n);
scanf(" %c", &c); /* пробел пропустит Enter, оставшийся после числа */
Частые ошибки
| Ошибка | Как правильно |
|---|---|
printf("%d", 3.14) | для дробного — %f |
scanf("%f", &d) для double | scanf("%lf", &d) |
printf("%lf", d) | в выводе достаточно %f |
| ширина меньше нужной | значение не обрежется, но колонки «разъедутся» |
%c сразу после числа | поставить пробел: " %c" |
точность у целых (%.2d) | у целых точность означает минимум цифр, обычно не нужна |
Мини-шпаргалка
printf("%-10d|%5d|%8.2f|\n", 7, 42, 3.5);
printf("%+d %05d %#x\n", 7, 42, 255); /* +7 00042 0xff */
printf("%.3f %.1f %.0f\n", 1.2345, 1.2345, 2.6);
int x;
double d;
scanf("%d %lf", &x, &d); /* несколько значений за раз */
scanf(" %c", &ch); /* символ после числа — с пробелом */
Что запомнить: ширина задаёт место под значение, точность — количество знаков после
точки; спецификатор ввода обязан совпадать с типом (%lf для double).