printf в C/C++: простыми словами

Привет! Здесь мы поговорим о функции printf. Эта функция доступна как в C, так и в C++, но влияние этой функции не ограничено этими двумя языками. Похожие функции вы сможете найти в Go, python, F#, и других.

Начнем мы с рассмотрения простых примеров использования printf, чтобы получить представление о том, как она работает. Потом мы посмотрим на разнообразие модификаторов, которые делают эту функцию настолько полезной и универсальной.

Как вывести строку на экран используя printf

Функция printf имеет следующий вид:

int printf ( const char * format, ... );
  • Первым аргументом она принимает указатель на строку, которая говорит этой функции, что и как нужно вывести на экран.
  • Далее функция принимает сколько угодно дополнительных параметров. Они будут использоваться в том случае, если format (первый аргумент) содержит упоминания этих самых дополнительных параметров. Тут мы будем передавать числа, строки и переменные, которые могут понадобиться для вывода на экран.
  • Возвращает функция сколько символов было выведено на экран.

Эта функция может показаться довольно сложной, но вам станет все понятнее после нескольких примеров:

#include <stdio.h>

int main() {
  printf("1. просто строка \n");
  printf("2. целое число: %d \n", 1234);
  printf("3. дробное число: %f \n", 12.34);
  printf("4. Символ: %c  \n", 'C');
  printf("5. строка: %s \n", "C++");
  printf("6. процент: 100%% \n");

  return 0;
}

Вывод этой программы:

1. просто строка 
2. целое число: 1234 
3. дробное число: 12.340000 
4. Символ: C  
5. строка: C++ 
6. процент: 100%

Давайте разберемся подробнее:

  1. Для вывода просто строки не нужно делать ничего особенного - просто передайте строку.
  2. Тут уже интереснее. Чтобы вывести целое число, которое передано дополнительным параметром, нам нужно его упомянуть в строке для форматирования. Для этого мы используем %d. В printf, все упоминания начинаются со знака %. После процента нужно указать как и что мы хотим вывести на экран. Для вывода целых чисел нужно указать букву d. Далее в статье мы разберем различные модификаторы, которые позволяют менять то, как именно это число будет выведено на экран.
  3. Для вывода числа с плавающей точкой float нужно использовать %f.
  4. Для char мы используем %c.
  5. Для строк подойдет %s.
  6. Но что делать если нам нужен просто процент? Не беда, для этого нужно просто указать процент два раза: %%. Тут логика похожа для вывода обратного слеша: \\.

Что будет выведено на экран:

#include <stdio.h>

int main() {
  int a = 10;
  float b = 20.5;
  char c = 'A';
  printf("дробное: %f, символ: %c\n", a, b, c);
  return 0;
}
дробное: 20.5, символ: A
дробное: 20.5, символ: 65
дробное: 20.500000, символ: A
дробное: 20, символ: A

Как видите, нет ничего сложного при работе с функцией printf в простых случаях. Давайте теперь пойдем немного дальше и отформатируем строку посложнее:

printf("1. несколько аргументов: %d, %f \n", 1234, 12.34);
printf("2. минимальная ширина: %10d \n", 1234);
printf("3. лидирующие нули: %010d \n", 1234);
printf("4. количество знаков после запятой: %.9f, %.0f \n", 12.34, 12.34);
printf("5. шестнадцатеричное число: %x \n", 1234);

Вывод:

1. несколько аргументов: 1234, 12.340000 
2. выравнивание:       1234 
3. лидирующие нули: 0000001234 
4. количество знаков после запятой: 12.340000000, 12 
5. шестнадцатеричное число: 4d2

Давайте разберемся с программой выше:

  1. В одной строке Можно производить как угодно много замен. Для этого достаточно указать несколько спецификаторов вроде %d или %s.
  2. Мы можем указать минимальную ширину просто написав число после %.
  3. Когда ширина заменяемого элемента оказывается меньше чем минимальная, printf по умолчанию использует пробелы. Мы можем сказать printf‘у использовать ноль вместо пробела просто дописав 0 после знака процента.
  4. Мы можем не только указывать минимальную ширину для заменяемого элемента, но и количество цифр после запятой у дробных чисел. Для этого просто напишите сколько цифр вы хотите видеть следующим образом: %.9f (девять чисел после запятой).
  5. printf можно заставить выводить целые положительные числа в системе счисления отличной от десятеричной. Для этого нужно использовать:
    • %x для шестнадцатеричных чисел;
    • %o для восьмеричных.

Поздравляю! Вы знаете большую часть того, что вам понадобиться при работе с printf. Если же вы хотите узнать больше о этой функции, то ниже мы разберем все спецификаторы, которые поддерживает printf.

Спецификаторы формата

Спецификатор формата имеет следующую структуру (в квадратных скобках опциональные модификаторы):

%[флаги][ширина][.точность][размер]тип

Обязательно нужно указать только знак вопроса и тип. Остальное можно опустить если вас устраивает вывод без них.

Тут довольно много различных модификаторов. Некоторые из них мы уже использовали выше, но большинство мы еще не встречали. Давайте пройдемся по каждому из них:

Тип

ТипОписаниеПримерВывод
d/iВыводит целое число

printf("%d", -1234);
printf("%i", -1234);

-1234
-1234

uВыводит целое число без знакаprintf("%u", 1234);1234
oВыводит целое восьмеричное число без знакаprintf("%o", 1234);2322
xВыводит целое число без знака в шестнадцатеричной системеprintf("%x", 1234);4d2
XКак x, только большими буквамиprintf("%X", 1234);4D2
fВыводит дробное числоprintf("%f", 12.34);12.340000
FКак f, только большими буквамиprintf("%F \n", 1. / 0);INF
eВыводит дробное число в экспоненциальной записиprintf("%e", 12.34);1.234000e+01
EКак e, только большими буквамиprintf("%E", 1234.);1.234000E+03
gВыводит дробное число, используя экспоненциальную запись если она короче

printf("%g", 12.34);
printf("%g", 12000000.34);

12.34
1.2e+07

GКак g, но большими буквами

printf("%G", 12.34);
printf("%G", 12000000.34);

12.34
1.2E+07

aВыводит дробное число в шестнадцатеричной системеprintf("%a", -12.34);-0x1.8ae147p+3
AКак a, только большими буквамиprintf("%A", -12.34);-0X1.8AE147P+3
cВыводит символprintf("%c", 'C');C
sВыводит строкуprintf("%s", "C++");C++
pВыводит указатель
void* p;
printf("%p", p);
0x104ddc000
nНичего не выводит. printf запишет количество символов, которые были выведены на экран до этого момента, в указатель переданный в соответствующем аргументе.
int n;
printf("n = %n", &n);
printf("%d", n);
n = 4
%Выводит процентprintf("%%");%

Флаги

ФлагОписаниеПримерВывод
-Выравнивает по левому краю

printf("%3d", 1);
printf("%-3d", 1);

1
1

+Выводит + для положительных чисел

printf("%+d", 1234);
printf("%+d", -1234);

+1234
-1234

Выводит для положительных чисел

printf("% d", 1234);
printf("% d", -1234);

1234
-1234

#Выводит 0, 0x, 0X перед числами типа %o, %x, %X соответственно (кроме нуля). Для дробных чисел выводит дробную часть независимо от ее наличия.

printf("%#o", 1234);
printf("%#x", 1234);
printf("%#x", 0);
printf("%#f", 12.34);
printf("%#f", 12.);
printf("%#f", 0.);

02322
0x4d2
0
12.340000
12.000000
0.00000

0Выводит нули вместо пробела, когда указана ширина

printf("%04d", 1);

0001

Ширина

ШиринаОписаниеПримерВывод
числоВыводит минимальное число символов

printf("%3d", 1);

1

*Как число, только оно передается в соответствующем аргументе

printf("%*d", 4, 1);

1

Точность

ТочностьОписаниеПримерВывод
.число

Для целых чисел (d, i, o, u, x, X) работает как ширина.

Для дробных (a, A, e, E, f, F) указывает, сколько дробных цифр нужно вывести. Если указан ноль, то ничего не будет выведено для 0.

Для g и G указывает, сколько значимых чисел (перед e) нужно вывести.

Для строк (s) указывает максимальное количество символов, которые будут выведены.

Если после точки число не указано, подразумевается ноль.

printf("%.4f", 12.34);
printf("%.0d", 0);
printf("%.1s", "C++");

12.3400
<пусто>
C

*Как число, только оно передается в соответствующем аргументе

printf("%.*f", 4, 12.34);

12.3400

Размер

Модификаторы размера нам нужны, потому что в C нет возможности понять размер переданного аргумента в printf. Давайте посмотри на простой пример, чтобы продемонстрировать о чем я говорю:

long long int x = 10000000000; // десять миллиардов
printf("%d\n", x); 

Вывод:

1410065408

Дело здесь в том, что printf ожидает int для спецификатора %d. Значение типа long long int просто не влезает, поэтому мы видим не то, что ожидали.

Чтобы решить эту проблему, нужно явно указать размер целого числа, которое нужно вывести:

long long int x = 10000000000; // десять миллиардов
printf("%lld\n", x);

Вывод:

10000000000

Теперь вывод соответствует нашим ожиданиям. Вот таблица возможных типов:

РазмерТип
hh

signed char / unsigned char

h

short int / unsigned short int

l

long int / unsigned long int

ll

long long int / unsigned long long int

j

intmax_t / uintmax_t

z

size_t

t

ptrdiff_t

L

long double

Упражнения

  1. Вывод строк с использованием printf:
    Напишите программу на C++, которая использует функцию printf для вывода различных типов данных: целое число, дробное число, символ, строку и процент. Продемонстрируйте использование различных модификаторов, например, минимальной ширины, лидирующих нулей, количества знаков после запятой и шестнадцатеричного числа.

  2. Форматирование строки с различными типами данных:
    Создайте программу, которая принимает от пользователя различные типы данных: целое число, дробное число, символ, строку и выводит их на экран, используя функцию printf с соответствующими модификаторами.

  3. Вывод значений в разных системах счисления:
    Напишите программу, которая запрашивает у пользователя целое положительное число и выводит его на экран в десятичной, восьмеричной и шестнадцатеричной системах счисления, используя функцию printf.

Обсуждение