Перейти к содержанию

Памятка: printf и scanf_s

К общим материалам · К лабораторным

Примеры рассчитаны на Visual Studio с компилятором MSVC и используют <stdio.h>. Имена записываются как printf и scanf_s, без std::. scanf_s доступна не во всех средах C++; в частности, в обычной среде GCC с glibc её нет. Если используете другую среду, согласуйте способ ввода с преподавателем.

Форматы для чисел

Тип переменной Ввод через scanf_s Вывод через printf
int %d %d
float %f %f
double %lf %lf

Перед переменной при чтении ставится &: программе нужно указать, куда записать число. При выводе & не ставится.

int count = 0;
float length = 0.0f;
double power = 0.0;

// Это отдельные примеры чтения; каждое чтение проверяется.
if (scanf_s("%d", &count) != 1) {
    printf("Input error\n");
    return 1;
}
if (scanf_s("%f", &length) != 1) {
    printf("Input error\n");
    return 1;
}
if (scanf_s("%lf", &power) != 1) {
    printf("Input error\n");
    return 1;
}

printf("count = %d\n", count);
printf("length = %.3f m\n", length);
printf("power = %.3lf W\n", power);

Для чтения чисел дополнительный аргумент с размером не нужен. Такой аргумент у scanf_s нужен для ряда символьных форматов, которые здесь не используются. Тип переменной и спецификатор должны совпадать: %f при чтении double — ошибка. Правила чтения и возвращаемого значения описаны в документации scanf_s.

Несколько чисел за один раз

double a = 0.0;
double b = 0.0;

printf("Enter a and b in meters: ");
if (scanf_s("%lf %lf", &a, &b) != 2) {
    printf("Input error\n");
    return 1;
}

Сравниваем возвращённое значение с числом ожидаемых записей. Здесь нужны две. Для трёх переменных ожидалось бы 3. Начальная запись = 0.0 не отменяет проверку чтения.

Ввод при ожидании двух чисел Результат чтения
2 3 Прочитаны оба числа
abc 3 Не прочитано ни одного числа
2 abc Прочитано только первое число

Число прочиталось — допустимо ли оно?

Предположим, обе длины должны принадлежать отрезку от 0.001 до 10 м включительно. После успешного чтения проверяем:

if (!(a >= 0.001 && a <= 10.0 &&
      b >= 0.001 && b <= 10.0)) {
    printf("Data error\n");
    return 1;
}

&& означает «и»: все четыре условия должны быть истинны. ! отрицает результат: внутрь if попадаем, если данные не удовлетворяют всей проверке. Проверяйте принадлежность разрешённому диапазону целиком; вычисление должно идти только после подтверждения допустимости всех входов.

Как вывести нужное количество цифр

printf("Result = %.3lf W\n", power);
printf("Result = %.10lf W\n", power);

%.3lf выводит double с тремя знаками после точки, %.10lf — с десятью. Для float аналогично используются %.3f и %.9f. Число после точки в формате задаёт количество знаков после десятичной точки, а не значащих цифр всего числа. Без указания точности %f и %lf выводят шесть знаков после точки. \n переводит строку. Литеральный знак процента печатается как %%. Форматы описаны в документации printf.

В материалах курса используем единое соглашение: %f для float, %lf для double — и при вводе, и при выводе. При чтении это обязательное соответствие типов. В printf форматы %f и %lf технически равнозначны: float при передаче автоматически преобразуется в double, а модификатор l не меняет вывод. Запись %lf для double выбрана для единообразия. Уже потерянные при расчёте цифры такое преобразование не восстанавливает.

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

  • В формате чтения указан %f, а переменная имеет тип double.
  • При чтении пропущен &.
  • Проверяется scanf_s(...) == 0, хотя часть значений тоже могла не прочитаться.
  • Деление выполняется раньше проверки знаменателя.
  • В конце формата чтения поставлен \n, из-за чего программа может ждать продолжения ввода.
  • Для вещественного результата используется %d.
  • Введена десятичная запятая вместо точки.