printf — Выводит отформатированную строку


Содержание

sprintf

(PHP 4, PHP 5, PHP 7)

sprintf — Возвращает отформатированную строку

Описание

Возвращает строку, созданную с использованием строки формата format .

Список параметров

Строка формата состоит из нуля и более директив: обычных символов (за исключением %), которые копируются напрямую в результирующую строку, и описателей преобразований, каждый из которых заменяется на один из параметров. Это относится как к sprintf() , так и к printf() .

Каждый описатель преобразований состоит из знака процента (%), за которым следует один или более дополнительных элементов (в том порядке, в котором они здесь перечислены):

  1. Необязательный описатель знака, указывающий как знак (- или +) будет применен к числу. По умолчанию используется только знак минус, если число отрицательное. Этот описатель заставляет положительные числа также отображать знак плюс.
  2. Необязательный описатель заполнения, который определяет, какой символ будет использоваться для дополнения результата до необходимой длины. Это может быть пробел или . По умолчанию используется пробел. Альтернативный символ может быть указан с помощью одинарной кавычки (). См. примеры ниже.
  3. Необязательный описатель выравнивания, определяющий выравнивание влево или вправо. По умолчанию выравнивается вправо, символ используется для выравнивания влево.
  4. Необязательное число, описатель ширины, определяющий минимальное число символов, которое будет содержать результат этого преобразования.
  5. Необязательный описатель точности, указанный в виде точки (.), после которой следует необязательная строка из десятичных чисел, определяющая, сколько десятичных разрядов отображать для чисел с плавающей точкой. При использовании со строками этот описатель выступает в роли обрезающей точки, устанавливающей максимальный лимит символов. Также между точкой и цифрой можно указать символ, используемый при дополнении числа.

Описатель типа, определяющий, как трактовать тип данных аргумента. Допустимые типы:

  • % — символ процента. Аргумент не используется.
  • b — аргумент трактуется как целое и выводится в виде двоичного числа.
  • c — аргумент трактуется как целое и выводится в виде символа с соответствующим кодом ASCII.
  • d — аргумент трактуется как целое и выводится в виде десятичного числа со знаком.
  • e — аргумент трактуется как число в научной нотации (например, 1.2e+2). Описатель точности указывает на количество знаков после запятой, начиная с версии PHP 5.2.1. В более ранних версиях он обозначал количество значащих цифр (на один знак меньше).
  • E — аналогично %e, но использует заглавную букву (например, 1.2E+2).
  • f — аргумент трактуется как число с плавающей точкой и также выводится в зависимости от локали.
  • F — аргумент трактуется как число с плавающей точкой и также выводится, но без зависимости от локали. Доступно, начиная с версии PHP 5.0.3.
  • g — выбирает самую краткую запись из %e и %f.
  • G — выбирает самую краткую запись из %E и %f.
  • o — аргумент трактуется как целое и выводится в виде восьмеричного числа.
  • s — аргумент трактуется как строка.
  • u — аргумент трактуется как целое и выводится в виде десятичного числа без знака.
  • x — аргумент трактуется как целое и выводится в виде шестнадцатеричного числа (в нижнем регистре).
  • X — аргумент трактуется как целое и выводится в виде шестнадцатеричного числа (в верхнем регистре).

Переменные будут преобразованы в соответвующий тип для спецификатора:

Обработка типов
Тип Спецификатор
string s
integer d, u, c, o, x, X, b
double g, G, e, E, f, F

Попытка использовать комбинацию строк и спецификаторов ширины с кодировками, которые требуют более одного байта на символ, может привести к неожиданным результатам.

В строке формата поддерживается нумерация и изменение порядка параметров. Например:

Пример #1 Изменение порядка параметров

= 5 ;
$location = ‘дереве’ ;

$format = ‘%d обезьян сидят на %s’ ;
echo sprintf ( $format , $num , $location );
?>

Пример #2 Изменение порядка параметров

Пример #3 Изменение порядка параметров

Пример #4 Изменение порядка параметров

Пример #5 Указание дополняющего символа

Результат выполнения данного примера:

Пример #6 Использование описателя позиции и совместно с другими описателями

Результат выполнения данного примера:

Попытка использовать спецификатор позиции, больший чем PHP_INT_MAX , приведет к генерации предупреждения функцией sprintf() .

Описатель типа c игнорирует дополнение строки и ее ширину

Возвращаемые значения

Возвращает строку, отформатированную в соответствии со строкой format , или FALSE в случае возникновения ошибки.

Примеры

Пример #7 sprintf() : заполнение нулями

= 43951789 ;
$u = — 43951789 ;
$c = 65 ; // ASCII 65 is ‘A’

// заметьте, двойной %% выводится как одинарный ‘%’
printf ( «%%b = ‘%b’\n» , $n ); // двоичное представление
printf ( «%%c = ‘%c’\n» , $c ); // выводит символ ascii, аналогично функции chr()
printf ( «%%d = ‘%d’\n» , $n ); // обычное целое число
printf ( «%%e = ‘%e’\n» , $n ); // научная нотация
printf ( «%%u = ‘%u’\n» , $n ); // беззнаковое целое представление положительного числа
printf ( «%%u = ‘%u’\n» , $u ); // беззнаковое целое представление отрицательного числа
printf ( «%%f = ‘%f’\n» , $n ); // представление числа с плавающей точкой
printf ( «%%o = ‘%o’\n» , $n ); // восьмеричное представление
printf ( «%%s = ‘%s’\n» , $n ); // строка
printf ( «%%x = ‘%x’\n» , $n ); // шестнадцатеричное представление (нижний регистр)
printf ( «%%X = ‘%X’\n» , $n ); // шестнадцатеричное представление (верхний регистр)

printf ( «%%+d = ‘%+d’\n» , $n ); // описатель знака с положительным целым числом
printf ( «%%+d = ‘%+d’\n» , $u ); // описатель знака с отрицательным целым числом
?>

Результат выполнения данного примера:

Пример #8 printf() : описатели строк

= ‘monkey’ ;
$t = ‘many monkeys’ ;

printf ( «[%s]\n» , $s ); // обычный вывод строки
printf ( «[%10s]\n» , $s ); // выравнивание вправо с пробелами
printf ( «[%-10s]\n» , $s ); // выравнивание влево с пробелами
printf ( «[%010s]\n» , $s ); // дополнение нулями также работает со строками
printf ( «[%’#10s]\n» , $s ); // использование собственного дополняющего символа ‘#’
printf ( «[%10.10s]\n» , $t ); // выравнивание влево с обрезкой в 10 символов
?>

Результат выполнения данного примера:

Пример #9 sprintf() : целые числа, дополненные нулями

Пример #10 sprintf() : форматирование денежных величин

Пример #11 sprintf() : научная нотация

echo sprintf ( «%.3e» , $number ); // выведет 3.625e+8
?>

Смотрите также

  • printf() — Выводит отформатированную строку
  • sscanf() — Разбирает строку в соответствии с заданным форматом
  • fscanf() — Обрабатывает данные из файла в соответствии с форматом
  • vsprintf() — Возвращает отформатированную строку
  • number_format() — Форматирует число с разделением групп
  • date() — Форматирует вывод системной даты/времени

printf()

Синтаксис:

printf ( (format, arg1[, arg2[, arg++]])

Поддерживается следующими версиями PHP:

Описание функции:

Функции printf() выводит отформатированную строку. Возвращает длину строки.

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

Возможные значения форматирования:

%% — Знак %
%b — трактуется как целое и выводится в виде двоичного числа
%c — трактуется как целое и выводится в виде символа с соответствующим кодом ASCII
%d — трактуется как целое и выводится в виде десятичного числа со знаком.
%e — трактуется как float и выводится в научной нотации (например 2.4e+3).
%E — аналогично %e, только выводит большую букву E (например 2.4E+3).
%u — трактуется как целое и выводится в виде десятичного числа без знака.
%f — трактуется как float и выводится в виде десятичного числа с плавающей точкой. (локальные настройки).
%F — трактуется как float и выводится в виде десятичного числа с плавающей точкой. (не локальные настройки).
%g — выводится то, что короче %e или %f .
%G — выводится то, что короче %E или %f .
%o — трактуется как целое и выводится в виде восьмеричного числа.
%s — трактуется как строка.
%x — трактуется как целое и выводится в виде шестнадцатеричного числа (в нижнем регистре букв).
%X — трактуется как целое и выводится в виде шестнадцатеричного числа (в верхнем регистре букв).

Дополнительные значения форматирования:

  • + (ставит знак «+» или «-» перед числами, по умолчанию ставится только перед отрицательными числами)
  • * ( символ используемый для заполнения результата до нужной длины.)
  • — (выравниватель влево, по умолчанию вправо)
  • [0-9] (минимальное число символов)
  • .[0-9] (описатель точности для чисел с плавающей точкой)

Дополнительные значения форматирования используются в выше перечисленном порядке.

arg1 Обязательный аргумент. Аргумент который должен быть вставлен в первую %знак конструкцию в аргументе format. mixed arg2, arg++ Необязательный аргумент. Аргумент который должен быть вставлен во вторую, третью и т.д %знак конструкцию в аргументе format. mixed

Примеры:

Пример 1:

$model = ‘жигули’;
$year = 1975;
$format = ‘Это %s %d года’;
printf($format, $model, $year);
?>

Это жигули 1975 года

Пример 2:

$ar = 7545;
$format = ‘%g’;
printf($format, $ar);
echo «
«;
$ar = 754576868;
printf($format, $ar);
?>

Пример 3:

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

$ar = 7545.4545;
$format = ‘%+0+9.2f’;
printf($format, $ar);
echo ‘
‘;
$format = ‘%+0-9.2f’;
printf($format, $ar);
?>

Пример 4:

Для изменение порядка следования параметров используется n\$

$model = ‘жигули’;
$year = 1975;
$format = «Это %2\$d года %1\$s «;
printf($format, $model, $year);
?>

Форматированный вывод. Функция printf

Пожалуйста, приостановите работу AdBlock на этом сайте.

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

Общий синтаксис функции printf следующий:

Рис.1. Общий синтаксис функции printf.

У функции printf есть один обязательный параметр – строка, заключенная в двойные кавычки. Эту строку еще называют формат-строкой .

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

Кроме обязательной строки форматирования есть и необязательные параметры. Они пишутся через запятую после формат-строки.

Формат-строка.

Любой символ в формат-строке относится к одной следующих групп:

  • символы, которые выводятся на экран без изменений
  • escape-последовательности
  • спецификаторы формата

Еscape-последовательности

С этой группой символов мы уже встречались в первом уроке. Символ \n . Он, как вы наверное помните, переносит выводимый текст на новую строку. Есть и другие эскейп-последовательности (иногда можно встретить название управляющие последовательности). Любая такая последовательность начинается с символа обратный слеш \ .

Часто используемые escape-последовательности:

\n — новая строка
\t — горизонтальная табуляция. Сдвигает выводимые данные вправо на ближайшую позицию табуляции. Обычно используется для выравнивания текста внутри строки.
\’ — вывод символа ‘
— вывод символа »
\\ — вывод символа \
\? — вывода символа ?

Как видите, последние четыре последовательности нужны лишь для того, чтобы вывести на экран символы «»», «’», «\» и «?». Дело в том, что если эти символы просто записать в формат-строку, то они не отобразятся на экране, а в некоторых случаях программа и вовсе не скомпилируется.

Следующая программа иллюстрирует работу escape-последовательностей.

Хотя escape-последовательности состоят из нескольких символов, но в потоке вывода они воспринимаются как цельный символ, который имеет своё собственное значение.

Итого, используя управляющие последовательности мы можем влиять на то, как данные будут выводиться на экране.

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

Спецификаторы формата всегда начинаются с символа % , и предназначены для вывода на экран значений переменных и выражений.

Для каждого типа данных есть свой спецификатор формата. Ниже записаны основные из них.

Основные спецификаторы формата:

%d, %i — целые числа
%f, %g — вещественные числа
%c — символы

Есть и другие спецификаторы формата. Мы познакомимся с ними тогда, когда они нам понадобятся.

Сами спецификаторы формата на экран не выводятся. Вместо них выводятся данные, которые передаются в функцию printf после строки форматирования.

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

Посмотрим на примерах.

Рис.2 Вывод Листинг 2.

Рис.3 Вывод Листинг 3.

Рис.4 Вывод Листинг 4.

Рис.5 Вывод Листинг 5.

На следующей картинке показан принцип работы функции printf .

Рис.6 Принцип работы функции printf.

По сути, формат строка задаёт некоторый трафарет(шаблон), в который подставляются данные для вывода, в том порядке, в котором они указаны.

Два основных правила, которые нужно соблюдать при работе с функцией printf :

  • количество спецификаторов формата должно совпадать с количеством данных для вывода
  • спецификаторы формата должны точно соответствовать типам выводимых данных

Пара примеров неправильного использования функции printf .

Напишем небольшую программу, которая иллюстрирует использование спецификаторов формата.

Модификаторы формата.

Обратите внимание, что вещественные числа через спецификатор %f выведены с шестью знаками после запятой. У вас на компьютере может быть выведено как больше, так и меньше знаков. Обычно такая точность не нужна. К счастью, этим можно управлять. Для этого предназначены модификаторы формата .

Модификаторы формата записываются между символом % и буквой используемого типа. На рисунке ниже представлена спецификатор формата с использованием модификатора формата.

Рис.7 Модификатор формата

Первое число обозначает ширину поля, выделяемого для записи числа. Второе число обозначает точность, с которой мы хотим вывести данное вещественное число.

В примере на картинке под вещественное число мы выделяем 8 символов и хотим видеть 3 знака после запятой.

Если указанного в ширине количества позиций нам не хватает для вывода числа, то ширина поля увеличивается автоматически, до минимально-возможного количества позиций.

У первого числа может спереди еще стоять знак минус, например %-8.3f . Этот минус говорит о том, что необходимо выровнять число по левому краю используемой области.

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

Результат работы данной программы представлен на рисунке ниже.

Рис.8 Вывод Листинг 8.

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

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

Да, чуть не забыл. Мы решили одну из задач, которая стояла перед нами в начале урока.

Практика

Решите предложенные задачи. Для удобства работы сразу переходите в полноэкранный режим

Исследовательские задачи для хакеров:

  1. Теперь вы можете увидеть, как выглядит мусор, который хранится в переменной после её объявления. Для этого объявите переменную любого типа и выведете её значение на экран использую функцию printf .
  2. Найдите в стандарте языка, в справочной системе компилятора полный список escape-последовательностей. Попробуйте использовать их в вашей программе. Разберитесь как они работают.
  3. Выясните, что произойдет, если в формат-строку функции printf вставить \c , где c — любой символ, не входящий в список escape-последовательностей. [K&R]
  4. Разберитесь с тем, как работает модификатор точности для целых чисел.
  5. Попробуйте вывести символы «»», «’», «\» и «?» без использования escape-последовательностей.
  6. Изучите как работает спецификатор %e

Дополнительные материалы

  1. Ранее я говорил, что тип double называется типом двойной точности, и что он в некотором смысле лучше, чем тип float . Запустите следующую программу, чтобы убедиться в этом.

Причина подобного результата в том, что количество памяти выделенное для хранения любой переменной ограничено Из-за этого вещественные числа хранятся в памяти компьютера приближенно. Для типа float памяти выделяется обычно меньше, чем для типа double . Поэтому возникают такие забавные моменты. Отдельно обратите внимание на результат деления целых чисел, записанный в переменную z . Об этом мы поговорим в следующем уроке.

Printf C: описание, форматирование, примеры

Стандартная функция консольного вывода в языке C – printf. Описание её содержится в заголовочном файле stdio.h. При помощи этой функции можно выводить данные или пользовательские сообщения в консоль. Язык C чувствителен к регистру. К примеру, две функции printf и scanf отличаются от подобных им Printf и Scanf. Все символы в функциях printf и scanf также должны быть записаны в нижнем регистре. Одним из простейших примеров C printf, выводящим на экран знакомое приветствие hello world, является:

Определение функций группы printf в файле «stdio.h»

Файл «stdio.h» относится к стандартной библиотеке ввода/вывода в языке С. Описание printf и подобных ей функций приводится в нём следующим образом:

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

Семейство функций printf

Функции группы printf в языке C служат для обработки и форматированного вывода данных в стандартный поток. Причём функции printf и vprintf производят запись в стандартный поток stdout, функции fprintf и vfprintf отправляют значения выводимых аргументов в некоторый заданный выходной поток, а snprintf, sprintf, vsnprintf и vsprintf записывают данные в символьную строку. Все перечисленные функции работают с использованием строки формата, указывающей необходимые преобразования аргументов для вывода.

Функция fprintf записывает результат в выходной поток stream. В буфер, представляющий собой символьную строку, выводит результат функция sprintf. Поведение функции не определено, если подлежащая выводу строка превышает размер массива буфера.

Функция snprintf так же, как и предыдущая, записывает данные в строковый буфер. Полученная строка символов завершается нулевым символом, если только bufsz (размер буфера) не равен нулю. Иначе, если значение bufsz равно нулю, то в буфер ничего не выводится, а сам буфер вполне может являться нулевым указателем, но возвращаемое значение (количество байтов, которое должно было быть записано) все равно вычисляется.

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

Подробнее рассмотрим функцию printf.

Общее описание

В языке C печать символов через стандартный поток вывода осуществляется посредством вызова функции printf. Команда printf в C форматирует набор выводимых данных, и они отправляются в стандартный поток вывода stdout. Значения, переданные в качестве аргументов функции, выводятся в консоль согласно указанной строке форматирования, которая в свою очередь заключает в себе две разновидности элементов. Первая разновидность — это символы, выводимые на экран, а элементы, определяющие особенности формата данных и отвечающие за метод представления аргументов при выводе, относятся ко второму виду.

При выводе переменных с printf в C особые комбинации символов в строке аргументов заменяются на преобразованные в соответствии с этими символами данные, причём для каждого типа данных существуют свои спецификации формата вывода.

Тип функции и возвращаемое значение

Функция printf, имеющая тип int, возвращает целочисленную величину, обозначающую количество напечатанных на экране символов. К примеру, можно присвоить:

int k = printf(«Привет %c %d %s», ‘a’, 11, «всем!»),

и тогда по значению переменной k легко определяется, возникла ли ошибка при выводе. В случае возврата отрицательного значения (если функция вернула «-1») можно сделать вывод, что произошла ошибка при её выполнении.

Синтаксис и зависимости

Чтобы использовать функцию printf, требуется подключить заголовочный файл «stdio.h» следующим образом:

Шаблон функции выглядит:

int printf(const char *формат, . )

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

Форма задания спецификаций формата:

Форматирование с printf в C выходных значений

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

Символ «%» указывает на начало спецификации формата вывода, следом за ним идёт код формата. Все поля в спецификации представляют собой отдельные, определяющие условия форматирования числа или символы.

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

Для явного указания, который по счёту аргумент нужно задействовать, возможно использовать «%m$» вместо «%» и «*m$» вместо «*», причём m, целочисленное десятичное значение, обозначает позицию нужного аргумента (индексирование начинается с единицы).


Параметры

stream Выходной поток для записи в файл
buffer Указатель на символьную строку для последующей записи в неё
bufsz Определяет число символов, допустимое для записи: максимальное значение — bufsz-1, и ещё нулевой ограничитель
format Указатель на многобайтовую строку с нулевым ограничителем, определяющую, как интерпретировать выводимые аргументы
Флаги, используемые в строке формата
Флаг Описание
Выравнивание результата по левому краю в поле вывода
+ При выводе численного значения, имеющего знак, принудительно печатается «+» перед положительной величиной (по умолчанию выводится только «-» перед отрицательным значением)
Для целых чисел и чисел с плавающей запятой ведущие нули используются вместо символов пробела для заполнения левых разрядов в случае, если задана ширина поля, превышающая длину числа. Для целых чисел флаг игнорируется, если явно указана точность. Для других преобразований с использованием этого флага поведение функции не определено. Флаг «0» не учитывается, если присутствует флаг «-«
space Если результат вывода выражения, имеющего знак, не начинается с символа этого знака или пуст, то пробел добавляется к результату. Флаг «space» игнорируется, если присутствует флаг «+»
# Выполняется альтернативная форма преобразования
Управляющие последовательности
Последовательность Результат
\a Звуковой сигнал
\n Перевод на новую строку
\r Возвращение курсора в начало строки
\t Табуляция
\v Вертикальная табуляция
Вывод двойной кавычки
\\ Вывод косой черты

Различные спецификаторы формата

Спецификатор формата Использование и описание для printf C Тип аргумента
% Запись литерала «%»
c Вывод одного символа. Происходит преобразование аргумента в тип unsigned char. При использовании модификатора «l» аргумент преобразуется в строку символов unsigned char
s Печать строки символов. Аргумент должен являться указателем на начальный элемент массива символов char char *
d
i
Вывод десятичного представления целочисленного значения со знаком int
o Вывод восьмеричного представления без знакового целочисленного значения unsigned int
x
X
Вывод шестнадцатеричного представления без знакового целочисленного значения. Символы «a», «b», «c», «d», «e», «f» применяются для преобразования «x». А для преобразования «X» — «A», «B», «C», «D», «E», «F» unsigned int
u Вывод десятичного преобразования без знакового целочисленного значения. Если преобразованное значение и точность вместе равны 0, то символы не выводятся unsigned int
f
F
Вывод десятичного представления числа с плавающей запятой, имеющего знак double
e
E
Вывод десятичного экспоненциального представления числа с плавающей запятой, округлённого и преобразованного так, что перед запятой остаётся одна цифра, а количество цифр после запятой соответствует точности представления (по умолчанию точность равна 6, а если указан 0, то символ запятой не выводится вообще). Символ «е» выводится в верхнем или нижнем регистре в зависимости от преобразования double
a
A
Вывод шестнадцатеричного представления числа с плавающей запятой double
g
G
Вывод десятичного представления числа с плавающей запятой или его десятичного экспоненциального представления в зависимости от значения и точности double
n Возврат числа элементов, выведенных функцией printf. Результат записывается в переменную, на которую указывает аргумент. Спецификация может не содержать флагов, ширины поля или точности int *
p Вывод указателя void *

Модификатор ширины поля

В строке формата в printf C может быть записано целое число после знака процента и перед командой форматирования. Оно является модификатором ширины поля и влияет на представление отображаемых данных. Наименьшая ширина поля, предназначенная для значения, определяется этим числом, и присутствие такого модификатора в случае, если аргумент оказывается меньше выделенного ему поля, вызывает добавление к результату пробелов или нулей. Заполнителем по умолчанию служит символ пробела, однако можно установить ноль, прописав его перед спецификацией ширины. Модификатор указывает минимум ширины, и любое превышающее этот минимум значение будет напечатано без помех. Число, к примеру, состоящее менее чем из восьми символов и печатаемое со спецификацией «%08d», окажется дополненным до необходимых восьми знаков нулями.

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

Модификатор точности

Модификатор точности служит для определения числа печатаемых десятичных знаков в представлении чисел. Для добавления модификатора точности необходимо поставить точку после спецификации ширины поля и указать нужное значение точности после неё. Модификатор точности определяется для «e», «f», «a», «E», «A» и «F» форматов. Для целых чисел модификатор устанавливает количество отображаемых цифр, добавляя нули в левый разряд, если нужно, а при выводе рациональных чисел определяет необходимое количество знаков после запятой. Применительно к строковым переменным: следующее после точки число в модификаторе точности служит определителем максимальной длины поля при выводе. К примеру, при заданной спецификации формата «%4.8s» будет выведена строка, длина которой находится в диапазоне от четырёх до восьми символов, в случае превышения крайние символы будут опущены.

Другие модификаторы формата

Выравниванием по умолчанию является выравнивание по правому краю, однако это можно изменить, поставив знак «-» после «%». Такая спецификация формата устанавливает выравнивание по левому краю.

Кроме того, функция printf способна различать короткие и длинные типы выводимых целых значений. Допустимые спецификаторы: «о», «d», «u», «i», «x» и «X». Длинный тип значения устанавливается модификатором «l», а короткий – модификатором «h». Например, при выводе длинного целого числа и значения типа short unsigned int спецификации формата выглядят как «%ld» и «%hu» соответственно.

Длина Описание
h Для типов short или unsigned short
l Для типов long или unsigned long
L Для типа long double

Примеры

1. Описание printf C и результаты вызова каждой функции:

2. Вывод на экран простого диалогового сообщения:

3. Программный код:

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

Данный пример иллюстрирует вывод на экран при помощи различных форматов строк, целочисленных переменных, символов, а также чисел с плавающей точкой.

Printf — Выводит отформатированную строку

Перевод статьи «Secrets of printf» [1], статья посвящена практическому применению оператора вывода printf.

Оператор printf — это просто функция языка C, которая выполняет форматированную печать неких значений, параметров функции. «Форматированную» — означает, что перед выводом параметров на печать параметры функции преобразуются в текст по особым правилам (формату), задаваемым специальной строкой, так называемой строкой форматирования. Точно такая же функция printf есть и на языке PERL. В этой заметке сделана попытка объяснить, как работает printf, и как правильно разработать соответствующую строку форматирования для любого случая.

[1. Основные понятия]

В старые времена программисты должны были писать свои собственные подпрограммы для ввода и вывода чисел. По сути это было не очень сложным делом. Сначала надо было выделить массив текстовых символов для хранения результата, затем просто разделить число на 10, запомнить остаток, добавить 0x30 для получения ASCII кода цифры, и сохранить цифру в конец массива. Далее эту процедуру нужно было повторить, чтобы найти все десятичные цифры числа. Затем нужно было вывести массив на печать. Все просто, не правда ли?

Однако несмотря на то, что просто (для гения типа Эйнштейна), однако все еще требует применения некоторых усилий. И что мы будем делать в более сложных случаях при проверке ошибок, или при выводе отрицательных чисел? Чтобы решить эти проблемы, программисты создали специальные библиотеки с предварительно написанными функциями вывода. И это было неплохо. В конечном счете самые популярные из этих функций были канонизированы для того, чтобы составить «стандартные» библиотеки.

Это означало, что теперь программистам не нужно было снова и снова выдумывать подпрограммы для печати чисел. Это также означало, что самые любимые опции вывода также должны были бы стать стандартными.

Так родился printf.

[2. Простая печать]

В самом простом случае функция printf получает один аргумент: строка символов, которая должна быть напечатана. Как ясно из названия, эта строка состоит из символов, каждый из которых будет выведен именно так, как он появляется в строке. Так, оператор printf(«xyz»); должен просто вывести сначала x, затем y, и наконец z. Это не является по-настоящему «форматированной» печатью (formatted printf), однако это базовая операция, которую может произвести printf.

2.1. «Натуральные» специальные символы

Чтобы идентифицировать начало строки, мы применили двойные («) кавычки в её начале. Чтобы идентифицировать конец строки, мы поместили двойные кавычки также и в конец строки. Но как быть, если нам нужно напечатать также и двойные кавычки? Мы не можем просто поместить двойные кавычки в печатаемую строку, потому что тогда этот символ будет ошибочно задавать маркер конца строки. Таким образом, двойные кавычки стали специальным символом. Для них уже не работает правило печатаю-то-что-вижу. Как все-таки напечатать двойные кавычки?

Различные языки программирования применяют разные способы для решения этой проблемы. Некоторые требуют, чтобы специальный символ был введен дважды. Язык C использует обратный слеш (делительная черта, \) в качестве управляющего символа (escape character), для изменения значения следующего за ним символа. Таким образом, для печати двойных кавычек нужно указать обратный слеш и за ним двойную кавычку (\»). Чтобы напечатать сам обратный слеш, то его нужно ввести дважды. Таким образом, первый обратный слеш означает «следующий символ имеет альтернативное значение», и второй обратный слеш теперь означает «напечатать обратный слеш».

Без обратного слеша специальные символы имеют свое натуральное специальное назначение. С обратным слешем они печатаются так, как видятся. В таблице приведен частный список примеров использования специальных символов.

\ escape, управляющая последовательность для следующего символа
\\ печатается обратный слеш
« обозначает начало или конец строки
печатаются двойные кавычки
начало или конец символьной константы
\’ печатается одинарная кавычка
% начало спецификации формата
\% печатается символ процента
%% также печатается символ процента

2.2. Альтернативные специальные символы

Однако еще у нас есть символы, которые печатаются без обратного слеша как обычно, но когда слева к ним добавляется обратный слеш, они становятся также спецсимволами. Например, это символ новой строки (new line, или line feed LF, код ASCII 0x0A). Чтобы напечатать букву n, нам нужно просто указать в строке n. Чтобы перевести печать на новую строку, мы должны напечатать \n, что вовлекает альтернативное значение для n (новая строка). В следующей таблице приведен список таких альтернативных спецсимволов.

\a звуковой сигнал, предупреждение (звоночек, bell)
\b backspace, вернуться на 1 символ назад (затереть символ)
\f form feed, переход на новый лист
\n newline, новая строка (linefeed, перевод строки, код ASCII 0x0D, переход печати на новую строку)
\r carriage return, возврат каретки (CR, код ASCII 0x0D, позиция печати возвращается на начало строки)
\t tab, табуляция по горизонтали
\v vertical tab, вертикальная табуляция

[3. Как задавать формат вывода числа (Format Specifications)]

Настоящая сила printf раскрывается при выводе на печать переменных. К примеру, мы можем указать спецификатор формата %d . Если такой спецификатор присутствует в строке, то мы должны предоставить число в качестве второго параметра функции printf. Функция printf сделана так, что может принимать неограниченное количество параметров, если это необходимо (printf относится к функциям с переменным количеством параметров). Пример ниже показывает, как это происходит.

В этом простом примере функция printf имеет 2 аргумента. Первый аргумент — строка «I am %d years old\n» (в ней содержится спецификатор формата %d ). Вторым аргументом является целое число age.

3.1. Список аргументов

Когда printf обрабатывает свои аргументы (список аргументов, отделенных друг от друга запятыми), он начинает печатать символы, которые находит в левом аргументе, символ за символом. Когда в этом процессе попадается символ процента (%), то printf знает, что это спецификатор формата — специальный набор символов, который задает, как надо вывести число. Следующее по порядку с списке аргументов число выводится так, как указано в спецификаторе формата. Затем процесс обработки символов (вывод их на печать) первого аргумента продолжается. Можно указать в строке 1 аргумента функции printf несколько спецификаторов формата. В этом случае 1 спецификатор будет выводить первый дополнительный аргумент, 2 спецификатор второй дополнительный аргумент и так далее, до конца строки. Вот еще один пример (указано 2 спецификатора формата и два дополнительных аргумента функции printf):

3.2 Символ процента (Percent, %)

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

%c выводит на печать одиночный символ (character)
%d выводит на печать десятичное число (представление числа с основанием 10)
%e выводит на печать числа с плавающей запятой (floating-point) в экспоненциальном формате
%f выводит на печать числа с плавающей запятой (floating-point)
%g выводит на печать числа с плавающей запятой (floating-point) в общем формате
%i выводит на печать десятичного целого числа (представление числа с основанием 10)
%o выводит на печать числа в восьмеричном формате (представление числа с основанием 8)
%s выводит на печать строки символов
%u выводит на печать целое десятичное число без знака (представление числа с основанием 10)
%x выводит на печать целого шестнадцатеричного числа (представление числа с основанием 16)
%% выводит на печать символ процента (можно использовать для этого также \%)

Самый простой вывод десятичного числа (целого и с плавающей точкой) требует указания только %d. В таблице приведены некоторые примеры аргументов printf и полученных результатов.

Имейте в виду, что в случае использования %d размер получаемой строки заранее не известен. Функция printf сгенерирует строку такого размера, какой нужен.

3.3. Опция ширины формата (Width Option)

Как уже упоминалось, простой печати чисел недостаточно. Есть другие желаемые опции. Возможно, самая важная из них — опция ширины формата. Если указать спецификатор формата %5d, то будет гарантировано, что вывод числа всегда займет 5 символьных позиций (если нужно, то больше, но никак не меньше). Эта возможность очень полезна при печати таблиц, потому что и большие, и маленькие числа займут в строке одинаковое место. Не так давно вся печать была моноширинной (monospaced, все символы по точкам в ширину были одинаковы), т. е. и символ w, и символ i занимали одинаковое место в строке по ширине. Это остается общим правилом в текстовых редакторах, используемых программистами.

Чтобы напечатать десятичное число определенной (как минимум заданной, не меньше) ширины, скажем шириной в 5 пробелов, спецификатор формата должен быть %5d. В таблице приведены простые примеры использования опции ширины (пробелы для наглядности показаны нижней квадратной скобкой).

Имейте в виду, что результат вывода будет дополнен слева пробелами до необходимой указанной ширины (для примеров в таблице это 5 символов). Слишком большие числа, которые требуют для печати большее количество символов, будут выведены полностью.

Чтобы добиться нормального использования, поле опции ширины должно быть указано таким, чтобы удовлетворять максимальному размеру ожидаемого выводимого числа. Например, если Ваши числа могут состоять из 1, 2 или максимум 3 цифр, то формат %3d подойдет. Опция ширины будет работать неправильно, если потребуется напечатать число, которое слишком большое, чтобы уместиться в заданную ширину поля. Функция printf примет решение вывести такие числа полностью, даже если они займут место больше, чем задано в спецификаторе ширины формата. Так сделано потому, что лучше вывести правильный ответ, пусть даже некрасиво, чем напечатать урезанный (неправильный) результат, и потом гадать, где же произошла ошибка.

3.4. Заполнение лишнего места

Когда печатается маленькое по размеру число наподобие 27 в поле формата %5d, встает вопрос — чем и как заполнить 3 другие (пустые) места печати. Цифры 27 можно напечатать по-разному: вывести в первых двух позициях, в последних двух позициях, или где-то посередине. Также пустые места могут быть заполнены не просто пробелами, а звездочками (***27, или 27***, или **27*), или знаками доллара ($$$27), или символами равенства (===27), или начальными нулями (наподобие 00027).

Эти дополнительные символы часто называют символами «проверочной защиты» (check protection), потому что они предназначены помешать плохим парням изменить печатаемую сумму в долларах. Относительно просто поменять заполнение пробелами на что-то другое. Гораздо сложнее подменить символ звездочки, знак доллара и ли символ равенства.

Функция printf предоставляет заполнение пространства пробелами (слева или справа), и заполнение нулями (только слева). Если Вам нужна check protection, или центрирование, то нужно использовать какие-то другие дополнительные методы. Но даже без check protection или центрирования printf
все равно имеет впечатляющую коллекцию опций форматирования.

3.5. Опция выравнивания (Justify Option)

Вывод на печать чисел функцией printf может быть выровнена влево (left-justified, напечатана в поле слева) или вправо (right-justified, напечатано в поле справа). Наиболее естественной выглядит печать чисел выровненными вправо, с дополнением пробелами слева. Так работает спецификатор формата %5d, он означает: напечатать число по основанию 10 в поле шириной 5 символов, и цифры числа выровнять по правому краю, слева дополнив нужным количеством пробелов.

Чтобы сделать число выровненным слева, к спецификатору формата нужно добавить знак минуса (-). Чтобы напечатать число в поле шириной в 5 символов, с выравниванием по левому краю спецификатор формата будет %-5d. В таблице приведены некоторые примеры использования левого выравнивания.

Так же, как и раньше, для коротких чисел результат будет дополнен справа пробелами. Слишком большие числа будут выведены без дополнения пробелами и не урезанные.

3.6. Заполнение лидирующими нулями (Zero-Fill Option)

Чтобы печать даты выглядела красиво и качественно, обычно одиночные цифры даты и месяца дополняют слева нулем. Это и есть «лидирующий ноль». Мы можем написать May 5, 2003, или как принято в США 05/05/2003. Можно написать также дату в виде 2003.05.05. Обратите внимание, что лидирующий ноль не изменяет значение дат, а просто добавляет наглядности. Таким способом отформатированная дата хорошо выглядит в списке.

Когда используется zero-filled (заполнение лидирующими нулями), нули всегда добавляются спереди, и результат получается выровненным как по левому, так и по правому краю. В этом случае знак минуса не дает эффекта. Чтобы вывести число в 5 позиций с дополнением нулями слева применяйте спецификатор формата %05d. В таблице показаны примеры использования и полученные результаты.

Короткие числа будут дополнены лидирующими нулями. Числа большого размера будут напечатаны как есть, без изменения.

3.7. Забава со знаками «плюс»

Отрицательные числа всегда будут выведены со знаком минуса (-). Положительные числа и нули обычно не печатаются со знаком, однако Вы можете это задать принудительно. Символ плюса (+) в спецификаторе формата делают такой запрос. Чтобы напечатать число со знаком в поле шириной 5 символов, спецификатор формата должен быть %+5d. В таблице показаны примеры использования и полученные результаты.

Имейте в виду, что 0 трактуется как положительное число. Короткие числа будут дополнены нужным количеством указанных заполнителей. Слишком большие числа будут выведены без дополнения и не урезанные.

Плюс и минус не связаны друг с другом. Они оба могут появляться в спецификаторе формата.

3.8. Невидимый знак «плюс»

Знак + немного причудлив, он может быть невидимым. В этом случае вместо печати + на положительных числах (и при печати 0), мы напечатаем пробел, где этот знак должен был бы находиться. Это может оказаться полезным при печати выровненных влево чисел, если Вы хотите, чтобы знак минуса значительно выделялся. В примерах ниже показаны два альтернативных варианта.

Помните о том, что спецификатор формата %-5d даст нам другой результат, который мы уже рассматривали ранее (он показан здесь снова для наглядности):

Имейте в виду, что знак + исчезает, но все еще занимает место слева от числа. Имейте в виду также, что мы можем скомбинировать некоторые опции в одном и том же спецификаторе формата. В этом случае мы имеем скомбинированные опции +, -, 5, или пробел, -, 5, или просто -, 5.

3.9. +, пробел и 0

Здесь приведен другой пример одновременного комбинирования некоторых опций в одном спецификаторе формата. Использование спецификаторов формата % 05d или %0 5d дадут нам следующие результаты:

Использование спецификаторов формата %+05d или %0+5d дадут нам следующие результаты:

Когда мы одновременно комбинируем + и пробел в одном спецификаторе формата, пробелы организуют пространство для знака, которое занимал бы знак +. Результат тот же, если бы даже пробел не был бы указан. Символ + имеет приоритет над пробелом.

3.10. Общие замечания по формату вывода

Опции вывода также называют флагами (flags), и между собой они могут появляться в любом порядке. В таблице приведен их частный список.

После опций если нужно, может быть указана минимальная ширина поля вывода.

[4. Вывод на печать строк]

Опция %s позволяет нам печатать строку внутри строки. Ниже дан пример.

Флаг левого выравнивания может быть применен к строкам, однако конечно же дополнение слева нулями (zero fill), знак +, и невидимый + являются бессмысленными.

[5. Вывод чисел с плавающей точкой (Floating Point)]

Числа с плавающей точкой наподобие 3.1415 содержат внутри себя точку. Обычные целые числа типа 27 не имеют такой точки.

Для печати чисел с плавающей точкой (float, double) флаги и правила работают точно так же, как и для целых чисел, но еще есть несколько новых опций. Самая важная указывает, какое количество цифр может появиться после десятичной точки. Это количество цифр называется точностью (precision) числа.

В обычной коммерции используются прайсы, где цены часто фигурируют как целые доллары или доллары и центы (precision составляет 0 или 2 цифры). Для цены на бензин цены упоминаются как доллары, центы, и десятая доля от цента (precision составляет 3 цифры). Ниже приведены примеры, как может быть выведено на печать число e=2.718281828.

Обратите внимание, что если в спецификаторе формата указаны точка и число, то это число (precision) указывает, сколько чисел должно появиться после десятичной точки.

Имейте в виду, что если не указаны точка и precision для %f, то по умолчанию будет приведен формат %.6f (6 цифр после десятичной точки).

Имейте также в виду, что если указана precision 0, то десятичная точка также исчезает. Если Вы хотите её вернуть, то нужно это сделать принудительно в виде простого текста (после спецификатора формата %f).

Мы можем указать оба и ширину (width), и точность (precision) одновременно в одном спецификаторе формата. Имейте в виду, что 5.2 означает общую длину 5, с 2 цифрами после десятичной точки. Самая распространенная ошибка, когда думают, что это означает 5 цифр до точки и 2 цифры после точки, но это неправильно. Будьте внимательны.

Можно также комбинировать precision с флагами, с которыми мы уже познакомились, чтобы указать левое выравнивание, дополнение слева нулями, применение знака +, и т. д.

[6. Как лучше всего разрабатывать формат]

Если Вы придумываете спецификатор формата, то первый шаг, который нужно сделать — решить, что именно Вы печатаете. Если это целое число (unsigned char, short, int, long), число с плавающей точкой (float, double), строка (char []) или одиночный символ (char), то Вы должны выбрать соответствующий спецификатор для базового типа формата.

Второй важный вопрос — какой ширины в символах должна быть печатаемое поле. Обычно это определяет самое большое по величине печатаемое число, которое Вы ожидаете при нормальной работе программы. Иногда этот размер определяется шириной предоставленного поля в форме или таблице (как например, в поле на кассовом чеке или на таблице счета-фактуры).

Решите, что Вы хотели бы увидеть на печати в различных ситуациях, в которых работает программа. В этой статье мы часто рассматривали результаты использования маленького положительного числа, маленького отрицательного числа, положительного числа вышедшего за установленный размер, отрицательного числа вышедшего за установленный размер. Опцию ширины Вы должны задать так, чтобы она хорошо подходила как к большим (но не превышающим максимальный размер), так и к малым числам. В самом простейшем случае можно разработать формат для корректного вывода самого большого числа, но если нужно обеспечить заданную относительную точность, то может потребоваться набор условных операторов с разными вариантами формата.

[7. Советы для тестирования]

Тест printf включает проверку появления подходящих проблем. Сам по себе алгоритм работы printf непрост для полного понимания — как будет работать вывод в разных ситуациях. Поэтому изучение тестового вывода printf даст более точную картину — что работает не так.

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

7.1. Простые случаи

Можно просто увидеть, есть ли у коротких чисел лидирующие нули. Если так, то в спецификаторе формата здесь должен быть 0. Также просто увидеть, есть ли у положительных чисел знак +. Если этот так, то + должен быть и в спецификации форматирования.

7.2. Перед, между, позади

Следующее, что нужно проверить — что печатается до выводимого числа, в промежутке, и после. К примеру, В спецификации форматирования типа x%5dz, где x стоит перед числом и z за числом. Части x и z не входят в спецификатор формата, но входят как часть в печатаемый результат. Все остальное относится к тому, что печатается «между».

Для того, чтобы определить, что же печатается за числом, посмотрите на вывод отрицательного числа чрезмерно большого размера. Любые пробелы до выведенного числа и после него покажут на пробелы до и после спецификатора формата. Например, если -2035065302 печатается как __-2035065302_ (здесь для наглядности пробелы заменены на подчеркивания), то можете быть уверенными, что строка печати была наподобие __%. _ , с двумя пробелами перед и одним пробелом после спецификатора формата. Это произошло потому, что чрезмерно большое число заняло все позиции, которые были отведены в спецификаторе формата.

Как только Вы определили, что перед, и что позади, Вы можете использовать эту информацию, чтобы сделать соответствующий выбор спецификатора формата. Часто бывает, что искомый ответ сразу становится очевидным.

7.3. Невидимый знак +

Сравните между собой вывод чрезмерно большого отрицательного и такого же положительного числа. Если положительное число имеет дополнительный пробел слева, то в этом месте формат задает невидимый знак +. Если слева от числа нет дополнительного пробела, но невидимый знак не задан.

7.4. Левое выравнивание

Вычтите друг из друга то, что перед, и то что позади. Посмотрите, что осталось слева. Посмотрите на вывод маленького отрицательного числа. Где Вы видите дополнительные печатаемые пробелы? Если они находятся спереди числа, то применено правое выравнивание числа. Если они находятся позади, то число выровнено при печати влево. Если пробелы есть и спереди, и сзади, значит Вы что-то делаете неправильно.

[8. Заключение]

Функция printf является мощным инструментом (в умелых руках) для вывода чисел и чего-нибудь еще, хранимого в переменных. Из-за того, что инструмент мощный и имеет много возможностей, он несколько сложен в освоении. Если попытаться использовать printf наобум, без изучения документации, то его сложность часто делает невозможным понимание принципа вывода. Однако при незначительном изучении сложность может быть развернута в простые возможности, включающие width (ширина поля вывода), precision (точность), signage (управление выводом знака), justification (выравнивание) и fill (заполнение пустых мест поля вывода). Если распознать и понять эти возможности, то printf становится удобным и надежным помощником при выводе значений на печать.

[Ссылки]

1. Secrets of “printf”, Professor Don Colton, Brigham Young University Hawaii .
2. IAR EWB ARM: форматированный вывод printf библиотеки DLIB.

Форматный вывод на Си для микроконтроллеров.

Форматированный ввод-вывод применяется очень широко, в первую очередь это, конечно, взаимодействие с пользователем, а так-же отладочный вывод, логи, работа с различными текстовыми протоколами и многое другое. В этой статье рассматриваются особенности применения форматированного вывода (ввод оставим на потом) для микроконтроллеров.
Первая программа написанная для ПК традиционно называется «Hello, world» и естественно пишет в стандартный вывод эту знаменитую фразу:

Первая программа для микроконтроллера обычно зовётся «Blinky» и она просто мигает светодиодом. Дело в том, что заставить работать традиционный «Hello, world» на микроконтроллере не так уж и просто для начинающего. Во первых, нет стандартного устройства вывода и его функциональность ещё нужно реализовать. Во вторых, не всегда бывает очевидно как подружить стандартные функции вывода с целевым устройством. Ситуация усугубляется тем, что в каждом компиляторе (тулчейне) это делается каким-то своим способом.

Форматный вывод.

Что-же, в общем, за зверь такой форматный вывод? Упрощенно говоря, это — вывод значений различных типов в виде текстовых полей.

Текстовое поле состоит из собственно значения, преобразованного в строку символов, и заполняющих символов для получения нужной ширины поля. Заполняющие символы могут находится слева или справа от значения, с помощью этого получается выравнивание по правому или левому краю соответственно. Заполнение также может находится внутри значения между определёнными его элементами, например между знаком и числом (как на рисунке), или между базой шестнадцатеричного числа (0x) и числом.
В качестве заполняющего символа обычно используется пробел, однако иногда могут использоваться нули, например в качестве ведущих нулей, или ещё что-нибудь.
Таким образом, форматированный вывод это — преобразование значений различных типов в текстовую форму и вывод их с определённым выравниванием и определённым заполнением.

Требования и особенности ввода-вывода для МК.

1. Гибкость. В отличии от старших братьев, для МК нет и не может быть стандартного устройства ввода-вывода. В каждой системе будет что-то своё, с уникальными требованиями и особенностями. В одной системе будет вывод в USART, во второй — на ЖК дисплей, в третей — в файл на SD карточке, в четвёртой — всё сразу. Значит система форматированного ввода-вывода должна быть достаточно гибкой, настраиваемой и независимой от аппаратных особенностей целевой платформы.

2. Требования к ресурсам. В МК ресурсов бывает мало и очень мало. В идеале, в прошивку МК должна попасть только та функциональность, которая реально используется. Скорость и размер кода имеют значение, под час решающее. Если мы не используем вывод типов с плавающей точкой, то и в полученной прошивке не должно быть кода, который его осуществляет.

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

4. Доступность. Библиотека ввода-вывода должна быть в наличии для целевой платформы.

5. Функциональность часто ставится на последнее место в угоду скорости и компактности.

Стандартная библиотека Си.

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

Это обычная функция с переменным числом параметров. Здесь первый аргумент fmt является форматной строкой, которая содержит, как обычный текст, так и специальные управляющие последовательности. Троеточие (. ) обозначает список дополнительных параметров, их может быть от нуля и до сколько поместится в стеке. Да, да все параметры в функцию printf передаются преимущественно в стеке (за исключением архитектуры ARM, где первые 4 параметра передаются в регистрах). Запихивает их в стек вызывающая функция, она-же инициализирует кадр стека перед вызовом и очищает после. Сама printf узнать сколько и каких параметров ей было передано может узнать только из форматной строки. При передачи параметров размером меньше (signed char, unsigned char, char и на некоторых платформах signed/unsigned short), чем int, они будут расширенны соответствующим расширением(знаковым или без-знаковым) до int-a. Это сделано для того, чтобы стек был всегда выровнен по границе машинного слова, а так-же уменьшает количество возможных ошибок при нестыковке размера фактического параметра и ожидаемого из форматной строки. Так-же параметры типа float при передаче в функции с переменным числом аргументов, приводятся к типу double.
Форматная строка содержит как символы непосредственно выводимые в поток, так и специальные управляющие последовательности, которые начинаются со знака «%». Управляющие последовательности имеют следующий формат:

Единственным обязательным элементом здесь является спецификатор, который определяет интерпретацию типа соответствующего параметра и может принимать следующие значения:

Флаги определяют дополнительные параметры форматирования (их может быть несколько):

Ширина — десятичное число, задаёт минимальное количество символов выводимых для соответствующего параметра. Если выводимое значение содержит меньше символов, чем указано, то оно будет дополнено пробелами (или нулями если есть флаг «0») до нужной ширины слева или справа, если указан флаг «-«. Например:

Если вместо десятичного числа указать «*», то значение ширины будет считанно из дополнительного целочисленного параметра. Это позволяет задавать значение ширины поля вывода из переменной:

Здесь первый раз i передаётся в качестве ширины поля, второй — значения.
Точность или длинна — десятичное число после знака точки «.». В случае вывода целых чисел этот элемент означает минимальное количество записанных знаков, если выводимое число короче указанной длинны, то оно дополняется ведущими нулями, если число длиннее, то оно не урезается.

Таким образом есть уже два способа вывести целое с нужным количеством ведущих нулей.
Для чисел с плавающей точкой в форматах «e», «E» и «f» этот элемент означает число знаков после десятичной точки. Результат округляется.

Для форматов «g» и «G» это — общее количество выведенных значимых цифр.

Для строк «s» этот элемент называется длинна и означает максимальное количество выведенных символов, обычно строки выводятся пока не встретится нулевой завершающий символ.

Также как и в элемента «ширина», в место точности можно поставить звёздочку и передать её значение в виде дополнительного целочисленного параметра:

Дополнительный модификатор служит для указания размерности типа:
h — применяется со спецификаторами i, d, o, u, x и X для знаковых и без-знаковых коротких целых short и unsigned short).
l — совместно со спецификаторами i, d, o, u, x и X означают длинные целые long и unsigned long).
l — совместно со спецификаторами s и c «широкие» многобайтные строку и символ соответственно.
L — обозначает тип long double, применяется со спецификаторами e, E, f, g и G.
В компиляторах поддерживающих тип long long, таких как GCC и IAR, часто есть для него нестандартный модификатор ll.
В стандарте С99 добавлены модификаторы «t» и «Z» для типов ptrdiff_t и size_t соответственно.

Работа над ошибками

Основным недостатком функций семейства printf считается вовсе не громоздкость и неторопливость — размер кода и накладные расходы на запихивание параметров в стек и разбор форматной строки обычно считаются приемлемыми, а подверженность ошибкам кодирования. Самое неприятное в этих ошибках то, что они могут быть неочевидными и проявляться не всегда, или не на всех платформах.
Большинство ошибок связано с несоответствием спецификаторов указанных в форматной строке с количеством и типами фактических аргументов. При этом можно выделить следующие ситуации:
— занимаемый в стеке размер параметров ожидаемых из форматной строки меньше размера фактически переданных. Типы фактические параметров совпадают с ожидаемыми. В этом случае просто выведутся параметры указанные в форматной строке, а лишние будут проигнорированы.
— занимаемый в стеке размер параметров ожидаемых из форматной строки меньше размера фактически переданных. Типы фактические параметров не совпадают с ожидаемыми. В этом случае параметры просто будут интерпретированы в соответствии с форматной строкой и в общем случае будет выведен мусор.
— размер фактических параметров меньше ожидаемых. Здесь поведение не определено и зависит от кучи разных факторов — от платформы, от компилятора, от содержимого стека на момент вызова printf. Поведение printf при этом может быть от внешне корректной работы и до чтения и даже записи произвольных участков памяти со всеми вытекающими последствиями.
Многие ошибки возникают при переносе кода с одной платформы на другую у которых отличаются размеры типов. Например:

На платформах, где int имеет 32 бита этот код работает правильно, а где int — 16 бит — будут выведены только 2 младших или старших (в зависимости от порядка следования байт) байта.
К счастью некоторые компиляторы, например GCC, знают printf «в лицо» и выдают предупреждения в случае несовпадения фактических параметров с форматной строкой. Однако это работает только если форматная строка задана литералом. А если она хранится в переменной (например extern указатель инициализируемый в другом модуле), то компилятор бессилен и проследить соответствеи параметров может быто очень не просто.

Особенности реализаций

AVR-GCC он-же WinAVR

В AVR-GCC, а точнее в avr-libc самая удачная, на мой взгляд, реализация стандартной библиотеки ввода-вывода Си. В ней имеется возможность выбирать необходимый функционал функций семейства printf. Они прекрасно работают со строками как RAM так и во Flash. Все функции семейства, включая snprintf и fprintf разделяют общий код и очень хорошо оптимизированы как по скорости, таки по объёму кода.
Для поддержки находящихся во Flash памяти строк введен новый спецификатор форматной строки %S — S — заглавная, строчная s по-прежнему означает строку в RAM. Но во Flash памяти может быть и сама форматная строка, для этого есть специальные модификации функций с суффиксом «_P» printf_P, fprintf_P, sprintf_P и т. д., которые ожидают форматную строку во Flash.
Для того чтобы printf заработала, нужно написать функцию вывода символа и определить файловый дескриптор стандартного вывода.

Помимо stdout есть стандартные дескрипторы stdin и stderr для стандартного ввода и стандартного вывода ошибок соответственно. Используя функцию fprintf можно явно указывать нужный файловый дескриптор и при необходимости можно определить сколько угодно устройств вывода:

В avr-libc имеется три уровня функциональности библиотеки ввода-вывода:
1. нормальный — поддерживается вся упомянутая выше функциональность, кроме вывода чисел с плавающей точкой. Этот режим включен по умолчанию и каких либо опций для него указывать не надо. Поддержка чисел с плавающей точкой занимает много места, а нужна сравнительно редко. Приведенный выше пример, скомпилированный с этим уровнем функциональности, занимает порядка 1946 байт Flash памяти.
2. минимальный — поддерживаются только самые базовые вещи: целые, строки, символы. Флаги, ширина поля и точность, если они есть в форматной строке, разбираются корректно, но игнорируются, поддерживается только флаг «#». Пример, скомпилированный с этим уровнем функциональности, занимает порядка 1568 байт Flash памяти. Его вполне можно было-бы применить на контроллере с 2 Кб flash памяти. Включается указанием в командной строке компоновщика («Linker options» в AVRStudio, а не компилятора, как расплывчато указано в документации avr-libc) следующих опций:

3. максимальный — полная функциональность, включая поддержку чисел с плавающей точкой. Включается опциями

Скомпилированный пример занимает при этом 3488 байт.
Функции семейства printf из avr-libc не используют буферизацию, не считая буферов для конвертации чисел, и выводят символы в устройство по мере их обработки. Поэтому, если буферизация нужна, то ее можно реализовать самостоятельно в функции вывода символа, там можно реализовать и кольцевой буфер и все, что угодно. Также в этих функциях не используется динамическая память, что в нашем случае очень хорошо, зато активно используется стек. Попробуем определить максимальное использование стека в них. Для этого в приложенном архиве заходим в каталог AvrGccPrintf, компилируем проект посредством AVRStudio и запускаем симуляцию с помощью runSimul.cmd.

После открывает образовавшийся файл trace.log, находим значение указателя стека (SP) после входа в main (после пролога), находим минимальное значение SP (стек растёт вниз) и вычитаем из первого второе. У меня получилось 0x455 — 0x429 = 0x2c = 44 байта использует сама функция fprintf, плюс еще 8 байт в стеке занимают ее параметры, итого 52 байта. Еще 14 байт занимает один файловый дескриптор и ещё 6 байт три стандартных указателя на файловые дескрипторы (stdout, stdin, stderr). Итого 72 байта RAM только на вызов fprintf, без учета всего остального.
Также из файла trace.log можно узнать общее время выполнения функций и где процессор проводит его больше всего.

Подробнее о стандартной библиотеке ввода-вывода avr-libc можно здесь:
www.nongnu.org/avr-libc/user-manual/group__avr__stdio.html

IAR for AVR

Здесь есть несколько версий Си-шных библиотек, с отличающейся функциональностью:
— CLIB — относительно маленькая, но ограниченная библиотека. Нет поддержки файловых дескрипторов, локалей и многобайтных символов. Считается устаревшей.
— Normal DLIB — более новая. Так-же нет поддержки файловых дескрипторов, локалей и многобайтных символов, но есть некоторые плюшки из стандарта С99.
— Full DLIB — полная библиотека Си. Поддерживает всё согласно стандарту С99, но при этом очень объёмная. Рассматривать этот вариант не буду, так, как размер функции printf отсюда превышает доступные 4 Кб кода для бесплатной версии IAR KickStart for AVR.
В IAR имеется возможность выбирать возможности для printf. Для этого заходим с меню Project->Options далее в диалоге General Options->Library Configuration. В списке «Printf formatter» можно выбрать необходимый уровень функционала. Для CLIB это Large, Small, Tiny, для DLIB добавляется еще Full. По возможностям эти уровни примерно соответствуют аналогичным в avr-gcc, поэтому расписывать их не буду.

Для того чтобы printf заработала, надо определить функцию вывода символа:

Разберём полный пример. Он также предназначен для запуска на симуляторе.

Тут выясняются две неприятные особенности. Во-первых функции printf и printf_P видимо не разделяют общий код и printf_P всегда использует максимальный форматтер, независимо от того, что выбрали в настройках для printf, занимая порядка 3500 байт кода. Поэтому приведенный пример не помещается в четыре бесплатных килобайта. Для проверки одну из функций надо закомментировать.
Во-вторых, ни printf, ни printf_P не умеют читать строки из flash памяти — для них нет спецификатора.
Размеры printf для различных уровней функциональности примерно соответствуют аналогичным у avr-gcc, где чуть меньше, где чуть больше — непринципиально. А вот использование стека в разы выше, минимальный размер стека данных, при котором printf заработала, составил 200 байт для DLIB и около 150 для CLIB. Так, что на контроллерах с 2 кб flash, 128 RAM использовать эти функции не получится.
Демо-проект находится в каталоге AvrIarPrintf. Для запуска симуляции, а точнее преобразования генерируемого IAR-ом hex-а в пригодный для потребления simulavr-ом elf, на машине должен быть установлен WinAVR (и прописан в переменной окружения PATH, естественно).

Mspgcc

В стандартной библиотеке mspgcc для форматного вывода реализованы только функции printf и sprintf, плюс еще нестандартная функция uprintf, которая принимает указатель на функцию вывода символа в качестве первого аргумента. Файловых дескрипторов там нет и в помине, выбирать уровень функциональности форматтеров тоже нельзя. При этом printf «весит» порядка двух килобайт так, что запустить её, скажем, на MSP43 Launchpad-е не получится.
Для работы printf нужно, вполне ожидаемо, определить функцию int putchar(int c):

IAR for MSP430, IAR for ARM и может еще какой IAR

Вообще в реализациях стандартной библиотеки от IAR Systems всё довольно однообразно для различных платформ, что не может не радовать. Как правило есть минимум две версии стандартной библиотеки — одна урезанная без поддержки файловых дескрипторов, вторая — полная, соответственно, с их поддержкой. Зовутся они как правило «Normal» и «Full» соответственно. Так-же в каждой из них можно выбирать необходимый функционал разбора форматной строки, поддерживаемый функциями семейства printf. Варианты уже уже описаны для IARfor AVR: Large, Small, Tiny и Full.
Если выбрать вариант библиотеки без файловых дескрипторов, то для работы функций вывода нужно определить лишь функцию int putchar(int outchar).
Если используем вариант с дескрипторами, то определить нужно функции __write, __lseek, __close и remove.
Минимальная их реализация, например, для STM32 может выглядеть так:

ARM + NewLib

Большинство сборок GCC под ARM используют NewLib в качестве стандартной библиотеки Си. Это достаточно взрослый проект и хорошо соответствует Си-шным стандартам, но при этом она относительно «тяжела» и требовательна к ресурсам. Для настройки библиотеки под свои нужды используется механизм системных вызовов. О нём уже немного писалось тут ispolzuem-libc-newlib-dlya-stm32, поэтому подробно на них останавливаться не буду, а упомяну об особенностях.
Первое это требования к памяти. Все stdio функции из NewLib используют хитрую буферизацию и динамически распределяют память для своих внутренних нужд. А значит им нужна куча и не маленькая, а в целых 3 Кбайт. Плюс примерно 1500 байт на статические структуры и плюс около 500 байт стека. Итого только чтоб напечатать «Hello, world!» нужно порядка 5 Кб оперативки. Что как-бы чуть больше, чем много для STM32-Discovery, на которой я запускал тестовый пример, с её 8 килобайтами. Также при использовании таких функций как printf по зависимостям тянется практически вся stdio плюс функции поддержки плавающей точки. В итоге тестовая прошивка занимает чуть меньше 30 Кб памяти программ. Если отказаться от использования чисел с плавающей точкой, то вместо printf можно использовать её облегченный аналог iprintf. В этом случае объём тестовой прошивки будет около 12 Кб.
Если какая либо из функций stdio не сможет выделить необходимую её память из кучи, то она тихонечко свалится в HardFault без объяснений причин.
Еще один момент это буферизация. Она может несколько запутать. Вызываем:

И… Ничего не происходит. Хотя системные вызовы правильно определены, куча настроена, места в ней хватает.
Наш вывод был спокойно положен в буфер и ждет там либо пока буфер не заполнится, либо не будет принудительно сброшен. Сбросить этот буфер можно с помощью функции fflush, или послав на вывод символ новой строки.

Режимом буферизации можно управлять с помощью функции setvbuf. Например, чтоб отключить буферизацию нужно сделать такой вызов до того, как в целевой поток был произведен какой либо вывод тыц:

При этом потребление памяти кучи уменьшится более чем на 1.5 Кб.


Xprintf

Это реализация функций похожих на printf от товарища Chan-а. Качаем отсюда:
elm-chan.org/fsw/strf/xprintf.html
Библиотека содержит следующие функции для форматированного вывода — аналоги функций стандартной библиотеки Си:

Все функции написаны целиком на Си и их можно использовать практически на любом микроконтроллере. Однако они не учитывают особенностей некоторых МК, например, нет никакой поддержки строк во Flash памяти для семейства AVR, что не добавляет удобства использования. Для использования xprintf необходимо инийиализировать указатель xfunc_out, присвоив ему адрес функции вывода символа. Рассмотрим пример. Компилятор avr-gcc, проект AvrStudio, рассчитан на запуск в симуляторе simulavr.

Здесь для вывода строк из Flash памяти их приходится предварительно скопировать в оперативку.
Из достоинств этой библиотеки можно выделить компактность кода (

1600 байт для приведённого примера) и лёгкость использования на различных платформах и модифицировать. На этом достоинства заканчиваются. Из недостатков стоит отметить
относительно медленную работу, примерно в полтора-два медленнее чем стандартная printf из avr-libc, и несоответствие стандартам — не поддерживаются некоторые флаги (‘пробел’, ‘ #’, ‘+’ ), спецификаторы (i, p n), не считая флагов для чисел с плавающей точкой и т.д.
Потребление стека порядка 38 байт не считая аргументов.

Описание примеров.

AvrGccPrintf
AvrIarPrintf
AvrXprintf
Msp430GccPrintf
Msp430IarPrintf
Stm32Format
IarArm

Работает на STM32 Discovery. Собирается с помощью IAR for ARM.

Итоги.

Преимущества использования стандартной библиотеки Си для форматного вывода:
— Стандартность. Этим всё сказано.
— Доступность. В каком-то виде есть практически в любом Си компиляторе.
— Разделение формата вывода и выводимых данных. Форматную строку легко вынести в отдельный файл/модуль, например для дальнейшей локализации.
— Хорошая функциональность.
Недостатки:
— Полностью стандартная реализация в большинстве случаев слишком «тяжела» для микроконтроллеров.
— Использование лишь одной функции, например printf, тянет за собой значительную часть библиотеки вывода, даже если реально используются только ограниченные возможности.
— Неаккуратное использование функций с форматной строкой может привести к трудно обнаруживаемым ошибкам кодирования.
— В каждом компиляторе используется какой-то свой способ для определения низкоуровневых функций вывода.

  • Си,
  • stdio,
  • printf,
  • stdout,
  • STM32,
  • AVR,
  • MSP430,
  • simulavr,
  • конкурс2
  • +7
  • 14 октября 2011, 09:21
  • neiver
  • 1

Комментарии ( 39 )

Пример, скомпилированный с этим уровнем функциональности, занимает порядка 1568 байт Flash памяти. Его вполне можно было-бы применить на контроллере с 2 Кб flash

  • reptile
  • 14 октября 2011, 11:36
  • neiver
  • 14 октября 2011, 12:33
  • reptile
  • 14 октября 2011, 12:54
  • neiver
  • 14 октября 2011, 13:00
  • Vga
  • 14 октября 2011, 13:08

100 байт свободно :)
Сам форматный вывод в примерно 1000 с небольшим байт помещается (и для AVR и для MSP430).
Об этом следующая статья будет. С шаблонами и выносом мозга.

  • neiver
  • 14 октября 2011, 13:16
  • Vga
  • 14 октября 2011, 13:24

Отличная статья – видно, что проделана большая работа.
Позволю себе небольшое дополнение: если говорить о выводе отладочной информации то такая информация как правило нужна только на этапе разработки. В релизном коде часто отладку отключают. Для того чтобы упростить процесс включения/отключения отладки можно применить директивы условной компиляции. Например, такая реализация:

Соответственно в коде для вывода отладки вместо printf используем _DBG, например

Теперь отладка будет выводиться, только если в определен символ _DEBUG, в противном случае вся откатка будет вырезана препроцессором.

printf

(PHP 4, PHP 5, PHP 7)

printf — Выводит отформатированную строку

Описание

Выводит строку, отформатированную в соответствии с аргументом format .

Список параметров

Строка формата состоит из нуля или более директив: обычные символы (за исключением %), которые просто выводятся без изменения и спецификаторы преобразования, каждый из которых требует передачи своего параметра.

Спецификаторы преобразования имеют следующий формат: %[flags][width][.precision]specifier.

Флаги

Флаг Описание
Выравнивание по левому краю в пределах заданной ширины поля; По умолчанию выравнивание происходит по правому краю.
+ Печатает плюс + у не отрицательных чисел; По умолчанию знак печатается только у отрицательных чисел.
(space) Дополняет результат пробелами. Это поведение по умолчанию.
Дополняет числа нулями (только слева). Со спецификатором s также может дополнять нулями справа.
(char) Дополняет результат символом (char).
Ширина

Целое число, определяющее минимальное количество символов, которое будет напечатано.

Точность

Точка . с последующим целым числом, работающая по разному для разных спецификаторов:

  • Для спецификаторов e, E, f и F: задает количество цифр после десятичной запятой (по умолчанию 6).
  • Для спецификаторов g и G: задает максимальное значение печатаемых значащих цифр.
  • Для спецификатора s: задает ограничение максимального количества символов в строке, которые будут выведены.

Замечание: Если указана точка без последующего значения точности, то точность будет считаться за 0.

Замечание: Попытка использовать спецификатор позиции со значением больше, чем PHP_INT_MAX приведет к выводу предупреждения.

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

Пусть P равно точности, если она не равно нулю, 6 — если точность не задана и 1, если точность задана как 0. Тогда, если преобразование со стилем «E» будет иметь показатель степени X:

Если P > X ≥ −4, преобразование будет в стиле «f» и точность будет P − (X + 1). В обратном случае, преобразование будет в стиле «e» и точность будет P − 1.

Спецификатор Описание
% Символ процента. Аргументы не требуются.
b Аргумент рассматривается как целое число и печатается в бинарном представлении.
c Аргумент рассматривается как целое число и печатается как символ из таблицы ASCII с соответствующим кодом.
d Аргумент рассматривается как целое число и печатается как целое число со знаком.
e Аргумент считается за число в научной нотации (т.е. 1.2e+2). Начиная с PHP 5.2.1, спецификатор точности задает количество цифр после десятичной запятой. В более ранних версиях он задавал общее количество значащих цифр (т.е. после запятой выводилось на 1 символ меньше).
E Аналогично спецификатору e, но использует заглавные символы (т.е. 1.2E+2).
f Аргумент считается за число с плавающей точкой (с учетом локали).
F Аргумент считается за число с плавающей точкой (без учета локали). Доступно с PHP 5.0.3.
g
G Аналогично спецификатору g, но использует E и F.
o Аргумент рассматривается как целое число и печатается в восмеричном представлении.
s Аргумент рассматривается и печатается как строка.
u Аргумент рассматривается как целое число и печатается как беззаковое целое число.
x Аргумент рассматривается как целое число и печатается в шестнадцатеричном представлении (буквы будут в нижнем регистре).
X Аргумент рассматривается как целое число и печатается в шестнадцатеричном представлении (буквы будут в верхнем регистре).

Спецификатор c игнорирует значения ширины и дополнения

Попытка использовать спецификаторы с указанием ширины для строки в многобайтовой кодировке может привести к неожиданным результатам.

Синтаксис описания формата: функции printf и wprintf Format specification syntax: printf and wprintf functions

Различные функции printf и wprintf принимают строку формата и необязательные аргументы и создают форматированную последовательность символов для выходных данных. The various printf and wprintf functions take a format string and optional arguments and produce a formatted sequence of characters for output. Строка формата не содержит ни одной или содержит несколько директив, которые являются либо литеральными символами для выходных данных, либо закодированными спецификациями преобразования, описывающими способ форматирования аргумента в выходных данных. The format string contains zero or more directives, which are either literal characters for output or encoded conversion specifications that describe how to format an argument in the output. Эта статья описывает синтаксис для кодирования спецификаций преобразования в строке формата. This article describes the syntax used to encode conversion specifications in the format string. Список этих функций см. в разделе Потоковый ввод-вывод. For a listing of these functions, see Stream I/O.

Спецификация преобразования состоит из необязательных и обязательных полей, имеющих следующий вид: A conversion specification consists of optional and required fields in this form:

Каждое поле спецификации преобразования — это символ или число, указывающее конкретный параметр формата или описатель преобразования. Each field of the conversion specification is a character or a number that signifies a particular format option or conversion specifier. Обязательное поле type определяет тип преобразования, которое применяется к аргументу. The required type field specifies the kind of conversion to be applied to an argument. Необязательные поля flags, width и precision управляют дополнительными аспектами формата, такими как начальные пробелы или нули, выравнивание и отображаемая точность. The optional flags, width, and precision fields control additional format aspects such as leading spaces or zeroes, justification, and displayed precision. Поле size указывает размер использованного и преобразованного аргумента. The size field specifies the size of the argument consumed and converted.

Базовая спецификация преобразования содержит только символ процента и символ type. A basic conversion specification contains only the percent sign and a type character. Например, %s определяет преобразование строк. For example, %s specifies a string conversion. Чтобы вывести символ знака процента, используйте %% . To print a percent-sign character, use %% . Если за символом процента следует символ, который не имеет смысла в поле формата, вызывается обработчик недопустимого параметра. If a percent sign is followed by a character that has no meaning as a format field, the invalid parameter handler is invoked. Дополнительные сведения см. в разделе Проверка параметров. For more information, see Parameter Validation.

Для обеспечения безопасности и стабильности убедитесь, что строки спецификации преобразования не определяются пользователем. For security and stability, ensure that conversion specification strings are not user-defined. Например, рассмотрим программу, которая предлагает пользователю ввести имя и сохраняет введенные данные в строковой переменной с именем user_name . For example, consider a program that prompts the user to enter a name and stores the input in a string variable that’s named user_name . Для печати переменной user_name не используйте следующий код: To print user_name , do not do this:

printf( user_name ); /* Danger! If user_name contains «%s», program will crash */

Вместо этого используйте следующий код: Instead, do this:

printf( «%s», user_name );

В Visual Studio 2015 семейство функций printf и scanf было объявлено как встроенное и перемещено в заголовки и . In Visual Studio 2015 The printf and scanf family of functions were declared as inline and moved to the and headers. При переносе старого кода вы можете увидеть ошибку LNK2020 в подключении к этим функциям. If you are migrating older code you might see LNK2020 in connection with these functions. Дополнительные сведения см. в разделе C++ журнал изменений Visual 2003-2015. For more information, see Visual C++ change history 2003 — 2015.

Спецификатор преобразования типов Type conversion specifier

Символ спецификации преобразования type определяет, как должен интерпретироваться соответствующий аргумент: как символ, строка, указатель, целое число или число с плавающей запятой. The type conversion specifier character specifies whether to interpret the corresponding argument as a character, a string, a pointer, an integer, or a floating-point number. Символ type — единственное обязательное поле спецификации преобразования; он указывается после всех необязательных полей. The type character is the only required conversion specification field, and it appears after any optional fields.

Аргументы, которые следуют за строкой формата, интерпретируются согласно соответствующему символу type и необязательному префиксу size. The arguments that follow the format string are interpreted according to the corresponding type character and the optional size prefix. Преобразования для символьных типов char и wchar_t определяются с помощью символов c или C; однобайтовые и многобайтовые строки или строки с расширенными символами указываются с помощью символа s или S, в зависимости от используемой функции форматирования. Conversions for character types char and wchar_t are specified by using c or C, and single-byte and multi-byte or wide character strings are specified by using s or S, depending on which formatting function is being used. Символьные и строковые аргументы, указанные с использованием c и s, интерпретируется как char и char* функциями семейства printf или как wchar_t и wchar_t* функциями семейства wprintf . Character and string arguments that are specified by using c and s are interpreted as char and char* by printf family functions, or as wchar_t and wchar_t* by wprintf family functions. Символьные и строковые аргументы, указанные с использованием C и S, интерпретируется как wchar_t и wchar_t* функциями семейства printf или как char и char* функциями семейства wprintf . Character and string arguments that are specified by using C and S are interpreted as wchar_t and wchar_t* by printf family functions, or as char and char* by wprintf family functions. Такое поведение относится только к системам Майкрософт. This behavior is Microsoft specific.

Целочисленные типы, такие как short , int , long , long long и их unsigned варианты, задаются с помощью d, i, o, u, xи x. Типы с плавающей запятой, такие как 1, 2 и 3, задаются с помощью, a, e, e, f, f, gи g. По умолчанию, если они не изменяются префиксом размера , целочисленные аргументы приводятся к типу 3, а аргументы с плавающей запятой приводятся к 4. Integer types such as short , int , long , long long , and their unsigned variants, are specified by using d, i, o, u, x, and X. Floating-point types such as float , double , and long double , are specified by using a, A, e, E, f, F, g, and G. By default, unless they are modified by a size prefix, integer arguments are coerced to int type, and floating-point arguments are coerced to double . В 64-разрядных системах тип int является 32-разрядным значением; поэтому 64-разрядные целые числа будут усекаться при форматировании для вывода, если не используется префикс size со значением ll или I64. On 64-bit systems, an int is a 32-bit value; therefore, 64-bit integers will be truncated when they are formatted for output unless a size prefix of ll or I64 is used. Для типов указателей, которые указываются с помощью символаp, используется размер указателя по умолчанию для платформы. Pointer types that are specified by p use the default pointer size for the platform.

Относится только к системам Майкрософт. Символ типа Z, а также поведение символов типа c, C, s и S при использовании с функциями printf и wprintf представляют собой расширения Майкрософт. Microsoft Specific The Z type character, and the behavior of the c, C, s, and S type characters when they are used with the printf and wprintf functions, are Microsoft extensions. C стандарта ISO постоянно использует c и s для узких символов и строк, и C и S — для расширенных символов и строк во всех функциях форматирования. The ISO C standard uses c and s consistently for narrow characters and strings, and C and S for wide characters and strings, in all formatting functions.

Символы поля типа Type field characters

Символ типа Type character Аргумент Argument Формат вывода Output format
c c Знак Character При использовании с функциями printf определяет однобайтовый символ; при использовании с функциями wprintf определяет расширенный символ. When used with printf functions, specifies a single-byte character; when used with wprintf functions, specifies a wide character.
C C Знак Character При использовании с функциями printf определяет расширенный символ; при использовании с функциями wprintf определяет однобайтовый символ. When used with printf functions, specifies a wide character; when used with wprintf functions, specifies a single-byte character.
d d Целое число Integer Десятичное целое число со знаком. Signed decimal integer.
i i Целое число Integer Десятичное целое число со знаком. Signed decimal integer.
o o Целое число Integer Восьмеричное целое число без знака. Unsigned octal integer.
u u Целое число Integer Десятичное целое число без знака. Unsigned decimal integer.
x x Целое число Integer Шестнадцатеричное целое число без знака, используются буквы «abcdef». Unsigned hexadecimal integer; uses «abcdef.»
X X Целое число Integer Шестнадцатеричное целое число без знака, используются буквы «ABCDEF». Unsigned hexadecimal integer; uses «ABCDEF.»
e e С плавающей запятой Floating-point Значение со знаком, имеющее формат [-]d.dddddd[d], где d — одна десятичная цифра, dddd — одна или несколько десятичных цифр в зависимости от указанной точности или шесть по умолчанию, dd[d] — две или три десятичные цифры в зависимости от формата вывода и величины экспоненты. Signed value that has the form [-]d.dddddd[d], where d is one decimal digit, dddd is one or more decimal digits depending on the specified precision, or six by default, and dd[d] is two or three decimal digits depending on the output format and size of the exponent.
E E С плавающей запятой Floating-point Аналогичен формату e, за исключением того, что вместо e порядок величины представляет символ E. Identical to the e format except that E rather than e introduces the exponent.
f f С плавающей запятой Floating-point Значение со знаком, имеющее формат [–]dddd . dddd, где dddd — одна или несколько десятичных цифр. Signed value that has the form [-]dddd.dddd, where dddd is one or more decimal digits. Количество цифр перед десятичной запятой зависит от величины числа, а количество знаков после десятичной запятой зависит от указанной точности либо используется шесть по умолчанию. The number of digits before the decimal point depends on the magnitude of the number, and the number of digits after the decimal point depends on the requested precision, or six by default.
F F С плавающей запятой Floating-point Идентичен формату f, за исключением того, что выходные данные бесконечности и NaN пишутся прописными буквами. Identical to the f format except that infinity and nan output is capitalized.
g g С плавающей запятой Floating-point Значения со знаком отображаются в формате f или e в зависимости от того, какой формат является более компактным для заданного значения и точности. Signed values are displayed in f or e format, whichever is more compact for the given value and precision. Формат e используется только в том случае, когда порядок значения меньше –4 или больше или равен значению аргумента precision. The e format is used only when the exponent of the value is less than -4 or greater than or equal to the precision argument. Нули в конце отбрасываются, а десятичная запятая отображается только в том случае, если за ней следует хотя бы одна цифра. Trailing zeros are truncated, and the decimal point appears only if one or more digits follow it.
G G С плавающей запятой Floating-point Аналогичен формату g, за исключением того, что вместоe порядок величины представляет символ E (где это необходимо). Identical to the g format, except that E, rather than e, introduces the exponent (where appropriate).
a a С плавающей запятой Floating-point Шестнадцатеричное значение с плавающей запятой двойной точности со знаком, которое имеет формат [−]0xh.hhhhdd, где h.hhhh — шестнадцатеричные цифры мантиссы (с использованием строчных букв) и dd — одна или более цифр порядка величины. Signed hexadecimal double-precision floating-point value that has the form [-]0xh.hhhhdd, where h.hhhh are the hex digits (using lower case letters) of the mantissa, and dd are one or more digits for the exponent. Точность определяет количество цифр после запятой. The precision specifies the number of digits after the point.
A A С плавающей запятой Floating-point Шестнадцатеричное значение с плавающей запятой двойной точности со знаком, которое имеет формат [−]0Xh.hhhhdd, где h.hhhh — шестнадцатеричные цифры мантиссы (с использованием заглавных букв) и dd — одна или более цифр порядка величины. Signed hexadecimal double-precision floating-point value that has the form [-]0Xh.hhhhdd, where h.hhhh are the hex digits (using capital letters) of the mantissa, and dd are one or more digits for the exponent. Точность определяет количество цифр после запятой. The precision specifies the number of digits after the point.
n n Указатель на целое число Pointer to integer Число символов, которые успешно записаны на данный момент в поток или буфер. Number of characters that are successfully written so far to the stream or buffer. Это значение хранится в целом числе, адрес которого указан в качестве аргумента. This value is stored in the integer whose address is given as the argument. Размер целочисленного значения, на которое ссылается указатель, управляется префиксом спецификации размера аргумента. The size of the integer pointed at can be controlled by an argument size specification prefix. Спецификатор n отключен по умолчанию. Дополнительные сведения см. в примечании по безопасности. The n specifier is disabled by default; for information see the important security note.
p p Тип указателя Pointer type Отображает аргумент как адрес в шестнадцатеричных цифрах. Displays the argument as an address in hexadecimal digits.
s s Строковое String При использовании с функциями printf определяет строку однобайтовых или многобайтовых символов; при использовании с функциями wprintf определяет строку расширенных символов. When used with printf functions, specifies a single-byte or multi-byte character string; when used with wprintf functions, specifies a wide-character string. Символы отображаются до первого нулевого символа или до тех пор, пока не будет достигнуто значение precision. Characters are displayed up to the first null character or until the precision value is reached.
S S Строковое String При использовании с функциями printf определяет строку расширенных символов; при использовании с функциями wprintf определяет строку однобайтовых или многобайтовых символов. When used with printf functions, specifies a wide-character string; when used with wprintf functions, specifies a single-byte or multi-byte character string. Символы отображаются до первого нулевого символа или до тех пор, пока не будет достигнуто значение precision. Characters are displayed up to the first null character or until the precision value is reached.
Z Z Структура ANSI_STRING или UNICODE_STRING ANSI_STRING or UNICODE_STRING structure Если в качестве аргумента передается адрес структуры ANSI_STRING или UNICODE_STRING, отображается строка, содержащаяся в буфере, на который указывает поле Buffer структуры. When the address of an ANSI_STRING or UNICODE_STRING structure is passed as the argument, displays the string contained in the buffer pointed to by the Buffer field of the structure. Используйте префикс-модификатор size для w, чтобы указать аргумент UNICODE_STRING , например %wZ . Use a size modifier prefix of w to specify a UNICODE_STRING argument—for example, %wZ . Поле Length структуры должно содержать значение длины строки в байтах. The Length field of the structure must be set to the length, in bytes, of the string. Поле MaximumLength структуры должно содержать значение длины буфера в байтах. The MaximumLength field of the structure must be set to the length, in bytes, of the buffer.

Как правило, символ типа Z используется только в функциях отладки драйвера, которые используют спецификацию преобразования, таких как dbgPrint и kdPrint . Typically, the Z type character is used only in driver debugging functions that use a conversion specification, such as dbgPrint and kdPrint .

Начиная с Visual Studio 2015, если аргумент, соответствующий описателю преобразования с плавающей запятой (a, A, e, E, f, F, g, G), равен бесконечности, не определен или не является числом (NaN), выводится форматированный результат, соответствующий стандарту C99. Starting in Visual Studio 2015, if the argument that corresponds to a floating-point conversion specifier (a, A, e, E, f, F, g, G) is infinite, indefinite, or NaN, the formatted output conforms to the C99 standard. В этой таблице перечислены форматированные выходные данные. This table lists the formatted output:

значения Value Вывод Output
infinity infinity inf
Несигнальное значение NaN Quiet NaN nan
Сигнальное значение NaN Signaling NaN nan(snan)
Неопределенное значение NaN Indefinite NaN nan(ind)

Любое из этих значение может иметь префикс в виде знака. Any of these values may be prefixed by a sign. Если символ описателя преобразования type с плавающей запятой является прописной буквой, выходные данные форматируются также прописными буквами. If a floating-point type conversion specifier character is a capital letter, then the output is also formatted in capital letters. Например, если спецификатором формата является %F вместо %f , бесконечность форматируется как INF вместо inf . For example, if the format specifier is %F instead of %f , an infinity is formatted as INF instead of inf . Функции scanf также могут анализировать эти строки, поэтому эти значения могут совершать круговой путь через функции printf и scanf . The scanf functions can also parse these strings, so these values can make a round trip through printf and scanf functions.

До выхода Visual Studio 2015 в среде CRT использовался другой нестандартный формат для выходных данных значений бесконечности, неопределенных значений и значений NaN. Before Visual Studio 2015, the CRT used a different, non-standard format for output of infinite, indefinite, and NaN values:

значения Value Вывод Output
+ бесконечность + infinity 1.#INF случайные цифры 1.#INF random-digits
— infinity — infinity -1.#INF случайные цифры -1.#INF random-digits
Неопределенное (то же, что и не число без вызова исключения) Indefinite (same as quiet NaN) цифра .#IND случайные цифры digit .#IND random-digits
NaN NaN цифра .#NAN случайные цифры digit .#NAN random-digits

Любое из этих значений могло иметь префикс в виде знака и могло быть отформатировано немного иначе в зависимости от ширины поля и точности (иногда с необычными эффектами). Any of these may have been prefixed by a sign, and may have been formatted slightly differently depending on field width and precision, sometimes with unusual effects. Например, printf(«%.2f\n», INFINITY) выводит 1.#J , так как #INF «округляется» до точности в два знака. For example, printf(«%.2f\n», INFINITY) would print 1.#J because the #INF would be «rounded» to 2 digits of precision.

Если аргумент, который соответствует %s или %S , или поле Buffer аргумента, который соответствует %Z , является указателем NULL, отображается значение «(NULL)». If the argument that corresponds to %s or %S , or the Buffer field of the argument that corresponds to %Z , is a null pointer, «(null)» is displayed.

Во всех экспоненциальных форматах минимальное отображаемое количество цифр показателя степени по умолчанию равно двум (три используются только при необходимости). In all exponential formats, the minimum number of digits of exponent to display is two, using three only if necessary. С помощью функции _set_output_format можно задать три отображаемых знака для обеспечения обратной совместимости с кодом, написанным для Visual Studio 2013 и более ранних версий. By using the _set_output_format function, you can set the number of digits displayed to three for backward compatibility with code written for Visual Studio 2013 and before.

Поскольку формат %n является небезопасным, по умолчанию он запрещен. Because the %n format is inherently insecure, it is disabled by default. Если в строке формата имеется символ %n , вызывается обработчик недопустимого параметра, как описано в разделе Проверка параметров. If %n is encountered in a format string, the invalid parameter handler is invoked, as described in Parameter Validation. Чтобы включить поддержку %n , изучите раздел _set_printf_count_output. To enable %n support, see _set_printf_count_output.

Директивы флагов Flag directives

Первое необязательное поле в спецификации преобразования содержит директивы флагов, ни одного или несколько символов флага, указывающих выравнивание выходных данных и управляющих выводом символов, пустых значений, начальных нулей, десятичных запятых и восьмеричных и шестнадцатеричных префиксов. The first optional field in a conversion specification contains flag directives, zero or more flag characters that specify output justification and control output of signs, blanks, leading zeros, decimal points, and octal and hexadecimal prefixes. В спецификации преобразования может быть указано несколько директив флагов, и символы флагов могут размещаться в любом порядке. More than one flag directive may appear in a conversion specification, and the flag characters can appear in any order.

Символы флагов Flag characters

Flag Flag Смысл Meaning Значение по умолчанию Default
Выравнивание результата по левому краю в пределах заданной ширины поля. Left align the result within the given field width. Выравнивание по правому краю. Right align.
+ Если выходное значение имеет тип со знаком, используйте для него префикс + или –. Use a sign (+ or -) to prefix the output value if it is of a signed type. Знак отображается только для отрицательных значений со знаком –. Sign appears only for negative signed values (-).
Если width предшествует префикс , добавляется несколько ведущих нулей для достижения минимальной ширины. If width is prefixed by , leading zeros are added until the minimum width is reached. Если отображаются и , игнорируется. If both and appear, the is ignored. Если указывается в целочисленном формате (i, u, x, X, o, d) и в сочетании со спецификацией точности, (например, %04.d ), знак игнорируется. If is specified for an integer format (i, u, x, X, o, d) and a precision specification is also present—for example, %04.d —the is ignored. Если указывается в формате плавающей запятой a или A, в начало мантиссы добавляются ведущие нули после префикса 0x или 0X . If is specified for the a or A floating-point format, leading zeros are prepended to the mantissa, after the 0x or 0X prefix. Без заполнения. No padding.
пустой (» «) blank (‘ ‘) Используйте пустой префикс для положительных выходных значений со знаком. Use a blank to prefix the output value if it is signed and positive. Пустой префикс игнорируется, если одновременно с ним присутствует флаг +. The blank is ignored if both the blank and + flags appear. Пустой префикс не отображается. No blank appears.
# Если используется в сочетании с форматом o, x или X, флаг # выводит префикс 0, 0x или 0X соответственно для всех ненулевых выходных значений. When it’s used with the o, x, or X format, the # flag uses 0, 0x, or 0X, respectively, to prefix any nonzero output value. Пустой префикс не отображается. No blank appears.
При использовании с форматом e, E, f, F, a или A флаг # принудительно добавляет к выходному значению десятичный разделитель. When it’s used with the e, E, f, F, a, or A format, the # flag forces the output value to contain a decimal point. Десятичный разделитель появляется, только если после него есть цифры. Decimal point appears only if digits follow it.
Если используется в сочетании с форматом g или G, флаг # принудительно добавляет десятичный разделитель к выходному значению и запрещает отбрасывать конечные нули. When it’s used with the g or G format, the # flag forces the output value to contain a decimal point and prevents the truncation of trailing zeros.

Флаг игнорируется в сочетании с форматами c, d, i, u или s. Ignored when used with c, d, i, u, or s. Десятичный разделитель появляется, только если после него есть цифры. Decimal point appears only if digits follow it. Конечные нули отбрасываются. Trailing zeros are truncated.

Спецификация ширины Width specification

В спецификации преобразования необязательное поле спецификации ширины отображается после любых символов флага. In a conversion specification, the optional width specification field appears after any flags characters. Аргумент width — неотрицательное целое десятичное число, управляющее минимальным количеством выводимых символов. The width argument is a non-negative decimal integer that controls the minimum number of characters that are output. Если количество символов в выходном значении меньше заданной ширины, к значениям слева или справа (в зависимости от того, определен ли флаг выравнивания по левому краю ( )) добавляются пробелы, в количестве, необходимом для достижения минимальной ширины. If the number of characters in the output value is less than the specified width, blanks are added to the left or the right of the values—depending on whether the left-alignment flag () is specified—until the minimum width is reached. Если параметр width имеет префикс 0, при преобразовании к целому числу или числу с плавающей запятой добавляются начальные нули до тех пор, пока не будет достигнута минимальная ширина, кроме случаев преобразования в бесконечность или NaN (не число). If width is prefixed by 0, leading zeros are added to integer or floating-point conversions until the minimum width is reached, except when conversion is to an infinity or NaN.

Спецификация ширины никогда не вызывает усечения значения. The width specification never causes a value to be truncated. Если число символов в выходном значении превышает указанную ширину или если аргумент width не задан, выводятся все символы значения в соответствии со спецификацией precision. If the number of characters in the output value is greater than the specified width, or if width isn’t given, all characters of the value are output, subject to the precision specification.

Если в качестве спецификации ширины указана звездочка ( * ), значение ширины задается аргументом int из списка аргументов. If the width specification is an asterisk ( * ), an int argument from the argument list supplies the value. Аргумент width должен предшествовать форматируемому значению в списке аргументов, как показано в следующем примере: The width argument must precede the value that’s being formatted in the argument list, as shown in this example:

printf(«%0*d», 5, 3); /* 00003 is output */

Отсутствующее или малое значение width в спецификации преобразования не приводит к усечению выходного значения. A missing or small width value in a conversion specification doesn’t cause the truncation of an output value. Если количество символов в результате преобразования больше значения параметра width, поле расширяется, чтобы вместить результат преобразования. If the result of a conversion is wider than the width value, the field expands to contain the conversion result.

Спецификация точности Precision specification

В спецификации преобразования третье необязательное поле является спецификацией точности. In a conversion specification, the third optional field is the precision specification. Эта спецификация состоит из точки (.), за которой следует неотрицательное целое десятичное число, которое, в зависимости от типа преобразования, определяет количество символов строки, количество десятичных разрядов или количество значащих цифр для вывода. It consists of a period (.) followed by a non-negative decimal integer that, depending on the conversion type, specifies the number of string characters, the number of decimal places, or the number of significant digits to be output.

В отличие от спецификации ширины, спецификация точности может вызывать либо усечение выходного значения, либо округление значения с плавающей запятой. Unlike the width specification, the precision specification can cause either truncation of the output value or rounding of a floating-point value. Если аргумент precision указан равным 0 и преобразуемое значение равно 0, никакие символы в результате выводиться не будут, как показано в следующем примере: If precision is specified as 0, and the value to be converted is 0, the result is no characters output, as shown in this example:

printf( «%.0d», 0 ); /* No characters output */

Если спецификация точности представляет собой звездочку (*), аргумент int из списка аргументов предоставляет значение. If the precision specification is an asterisk (*), an int argument from the argument list supplies the value. В списке аргументов аргумент precision должен предшествовать форматируемому значению, как показано в следующем примере: In the argument list, the precision argument must precede the value that’s being formatted, as shown in this example:

printf( «%.*f», 3, 3.14159265 ); /* 3.142 output */

Символ type определяет либо интерпретацию аргумента precision, либо точность по умолчанию при опущенном аргументе precision, как показано в следующей таблице. The type character determines either the interpretation of precision or the default precision when precision is omitted, as shown in the following table.

Влияние значений точности на тип How Precision Values Affect Type

Type Type Смысл Meaning Значение по умолчанию Default
a, A a, A Точность определяет количество цифр после запятой. The precision specifies the number of digits after the point. Точность по умолчанию — 13. Default precision is 13. Если точность равна 0, десятичная запятая не выводится, если не используется флаг # . If precision is 0, no decimal point is printed unless the # flag is used.
c, C c, C Точность не применяется. The precision has no effect. Символ выводится. Character is printed.
d, i, o, u, x, X d, i, o, u, x, X Точность определяет минимальное выводимое количество цифр. The precision specifies the minimum number of digits to be printed. Если количество цифр в аргументе меньше значения precision, выходное значение дополняется слева нулями. If the number of digits in the argument is less than precision, the output value is padded on the left with zeros. Значение не усекается, когда количество цифр превышает значение precision. The value is not truncated when the number of digits exceeds precision. Точность по умолчанию — 1. Default precision is 1.
e, E e, E Выводимое количество знаков дробной части задается спецификацией точности. The precision specifies the number of digits to be printed after the decimal point. Последняя выводимая цифра округляется. The last printed digit is rounded. Точность по умолчанию — 6. Default precision is 6. Если аргумент precision равен 0 или присутствует точка (.) без числа после нее, десятичная запятая не выводится. If precision is 0 or the period (.) appears without a number following it, no decimal point is printed.
f, F f, F Значение точности задает количество цифр после десятичной запятой. The precision value specifies the number of digits after the decimal point. Если десятичная запятая присутствует, перед ней присутствует по крайней мере одна цифра. If a decimal point appears, at least one digit appears before it. Значение округляется до соответствующего количества цифр. The value is rounded to the appropriate number of digits. Точность по умолчанию — 6. Default precision is 6. Если аргумент precision равен 0 или если присутствует точка (.) без числа после нее, десятичная запятая не выводится. If precision is 0, or if the period (.) appears without a number following it, no decimal point is printed.
g, G g, G Точность определяет максимальное выводимое количество значащих цифр. The precision specifies the maximum number of significant digits printed. Выводятся шесть значащих цифр, а конечные нули усекаются. Six significant digits are printed, and any trailing zeros are truncated.
s, S s, S Точность определяет максимальное количество выводимых символов. The precision specifies the maximum number of characters to be printed. Символы, выходящие за рамки precision, не выводятся. Characters in excess of precision aren’t printed. Символы выводятся до тех пор, пока не будет обнаружен нуль-символ. Characters are printed until a null character is encountered.

Спецификация размера аргумента Argument size specification

В спецификации преобразования поле size — это модификатор длины аргумента для описателя преобразования type. In a conversion specification, the size field is an argument length modifier for the type conversion specifier. Префиксы поля size для поля type (hh, h, j, l (строчная L), L, ll, t, w, z, I (прописная i), I32 и I64) определяют «размер» соответствующего аргумента — длинный или короткий, 32- или 64-разрядный, однобайтовый или расширенный символ — в зависимости от описателя преобразования, который они модифицируют. The size field prefixes to the type field—hh, h, j, l (lowercase L), L, ll, t, w, z, I (uppercase i), I32, and I64—specify the «size» of the corresponding argument—long or short, 32-bit or 64-bit, single-byte character or wide character—depending on the conversion specifier that they modify. Эти префиксы размера используются с символами type в семействах функций printf и wprintf для определения интерпретации размеров аргументов, как показано в следующей таблице. These size prefixes are used with type characters in the printf and wprintf families of functions to specify the interpretation of argument sizes, as shown in the following table. Поле size является необязательным для некоторых типов аргументов. The size field is optional for some argument types. Если префикс размера не указан, модуль форматирования использует целые аргументы, например подписанные или не подписанные char , short , int , long и типы перечисления как 32-разрядные типы int , а аргументы float , double и long double с плавающей запятой используются как 64-разрядные типы double . When no size prefix is specified, the formatter consumes integer arguments—for example, signed or unsigned char , short , int , long , and enumeration types—as 32-bit int types, and float , double , and long double floating-point arguments are consumed as 64-bit double types. Такое поведение соответствует правилам повышения уровня аргументов по умолчанию для списков аргументов переменных. This behavior matches the default argument promotion rules for variable argument lists. Дополнительные сведения о повышении аргументов см. раздел Ellipses and Default Arguments (Многоточия и аргументы по умолчанию) в статье Postfix expressions (Постфиксные выражения). For more information about argument promotion, see Ellipses and Default Arguments in Postfix expressions. Как в 32-разрядной, так и в 64-разрядной системах спецификация преобразования 64-разрядного целого аргумента должна включать префикс размера ll или I64. On both 32-bit and 64-bit systems, the conversion specification of a 64-bit integer argument must include a size prefix of ll or I64. В противном случае поведение модуля форматирования не определено. Otherwise, the behavior of the formatter is undefined.

Некоторые типы имеют разный размер в 32-разрядном и 64-разрядном коде. Some types are different sizes in 32-bit and 64-bit code. Например, size_t на 32 бита длиннее в коде, скомпилированном для x86, и на 64 бита длиннее в коде, скомпилированном для x64. For example, size_t is 32 bits long in code compiled for x86, and 64 bits in code compiled for x64. Чтобы создать код форматирования для типов с переменным количеством байт, не зависящий от платформы, можно использовать модификатор размера аргумента с переменным количеством байт. To create platform-agnostic formatting code for variable-width types, you can use a variable-width argument size modifier. Кроме того, можно использовать 64-разрядный модификатор размера аргумента и явно повысить тип аргумента с переменным количеством байт до 64 бит. Alternatively, use a 64-bit argument size modifier and explicitly promote the variable-width argument type to 64 bits. Присущий Майкрософт модификатор размера аргумента I (прописная i) обрабатывает целочисленные аргументы переменной ширины, но для обеспечения переносимости рекомендуется использовать характерные для типа модификаторы j, t и z. The Microsoft-specific I (uppercase i) argument size modifier handles variable-width integer arguments, but we recommend the type-specific j, t, and z modifiers for portability.

Префиксы размера для описателей формата функций printf и wprintf Size Prefixes for printf and wprintf Format-Type Specifiers

Чтобы указать To specify Используемый префикс Use prefix Со спецификатором типа With type specifier
char
unsigned char
hh hh d, i, o, u, x или X d, i, o, u, x, or X
short int
short unsigned int
h h d, i, o, u, x или X d, i, o, u, x, or X
__int32
unsigned __int32
I32 I32 d, i, o, u, x или X d, i, o, u, x, or X
__int64
unsigned __int64
I64 I64 d, i, o, u, x или X d, i, o, u, x, or X
intmax_t
uintmax_t
j или I64 j or I64 d, i, o, u, x или X d, i, o, u, x, or X
long double l (строчная L) или L l (lowercase L) or L a, A, e, E, f, F, g или G a, A, e, E, f, F, g, or G
long int
long unsigned int
l (строчная L) l (lowercase L) d, i, o, u, x или X d, i, o, u, x, or X
long long int
unsigned long long int
ll (строчные LL) ll (lowercase LL) d, i, o, u, x или X d, i, o, u, x, or X
ptrdiff_t t или I (прописная i) t or I (uppercase i) d, i, o, u, x или X d, i, o, u, x, or X
size_t z или I (прописная i) z or I (uppercase i) d, i, o, u, x или X d, i, o, u, x, or X
Однобайтовый символ Single-byte character h h c или C c or C
Расширенный символ Wide character l (строчная L) или w l (lowercase L) or w c или C c or C
Строка однобайтовых символов Single-byte character string h h s, S или Z s, S, or Z
Строка расширенных символов Wide-character string l (строчная L) или w l (lowercase L) or w s, S или Z s, S, or Z

Типы ptrdiff_t и size_t являются __int32 или unsigned __int32 на 32-разрядных платформах и __int64 или unsigned __int64 на 64-разрядных платформах. The ptrdiff_t and size_t types are __int32 or unsigned __int32 on 32-bit platforms, and __int64 or unsigned __int64 on 64-bit platforms. Префиксы размера I (прописная i), j, t и z принимают правильное значение ширины аргументов для платформы. The I (uppercase i), j, t, and z size prefixes take the correct argument width for the platform.

В Visual C++ хотя long double является отдельным типом, он имеет то же внутреннее представление, что и тип double . In Visual C++, although long double is a distinct type, it has the same internal representation as double .

Спецификатор типа hc или hC аналогичен c в функциях printf и C в функциях wprintf . An hc or hC type specifier is synonymous with c in printf functions and with C in wprintf functions. Спецификатор типа lc, lC, wc или wC аналогичен C в функциях printf и c в функциях wprintf . An lc, lC, wc, or wC type specifier is synonymous with C in printf functions and with c in wprintf functions. Спецификатор типа hs или hS аналогичен s в функциях printf и S в функциях wprintf . An hs or hS type specifier is synonymous with s in printf functions and with S in wprintf functions. Спецификатор типа ls, lS, ws или wS аналогичен S в функциях printf и s в функциях wprintf . An ls, lS, ws or wS type specifier is synonymous with S in printf functions and with s in wprintf functions.

Относится только к системам Майкрософт. Префиксы модификатора размера аргумента I (прописная i), I32, I64 и w являются расширениями Майкрософт и не совместимы с C стандарта ISO. Microsoft Specific The I (uppercase i), I32, I64, and w argument size modifier prefixes are Microsoft extensions and are not ISO C-compatible. Префикс h при использовании с данными типа char и префикс l (строчная L) при использовании с данными типа double являются расширениями Майкрософт. The h prefix when it’s used with data of type char and the l (lowercase L) prefix when it’s used with data of type double are Microsoft extensions.

printf

printf — Выводит отформатированную строку

Описание

Выводит строку, отформатированную в соответствии с аргументом format .

Список параметров

Описание параметра format смотрите в описании функции sprintf() .

Возвращаемые значения

Возвращает длину выведенной строки.

Смотрите также

  • print — Выводит строку
  • sprintf() — Возвращает отформатированную строку
  • vprintf() — Выводит отформатированную строку
  • sscanf() — Разбирает строку в соответствии с заданным форматом
  • fscanf() — Обрабатывает данные из файла в соответствии с форматом
  • flush() — Сброс системного буфера вывода

sprintf

(PHP 4, PHP 5, PHP 7)

sprintf — Возвращает отформатированную строку

Описание

Возвращает строку, созданную с использованием строки формата format .

Список параметров

Строка формата состоит из нуля и более директив: обычных символов (за исключением %), которые копируются напрямую в результирующую строку, и описателей преобразований, каждый из которых заменяется на один из параметров. Это относится как к sprintf() , так и к printf() .

Каждый описатель преобразований состоит из знака процента (%), за которым следует один или более дополнительных элементов (в том порядке, в котором они здесь перечислены):

  1. Необязательный описатель знака, указывающий как знак (- или +) будет применен к числу. По умолчанию используется только знак минус, если число отрицательное. Этот описатель заставляет положительные числа также отображать знак плюс.
  2. Необязательный описатель заполнения, который определяет, какой символ будет использоваться для дополнения результата до необходимой длины. Это может быть пробел или . По умолчанию используется пробел. Альтернативный символ может быть указан с помощью одинарной кавычки (). См. примеры ниже.
  3. Необязательный описатель выравнивания, определяющий выравнивание влево или вправо. По умолчанию выравнивается вправо, символ используется для выравнивания влево.
  4. Необязательное число, описатель ширины, определяющий минимальное число символов, которое будет содержать результат этого преобразования.
  5. Необязательный описатель точности, указанный в виде точки (.), после которой следует необязательная строка из десятичных чисел, определяющая, сколько десятичных разрядов отображать для чисел с плавающей точкой. При использовании со строками этот описатель выступает в роли обрезающей точки, устанавливающей максимальный лимит символов. Также между точкой и цифрой можно указать символ, используемый при дополнении числа.

Описатель типа, определяющий, как трактовать тип данных аргумента. Допустимые типы:

  • % — символ процента. Аргумент не используется.
  • b — аргумент трактуется как целое и выводится в виде двоичного числа.
  • c — аргумент трактуется как целое и выводится в виде символа с соответствующим кодом ASCII.
  • d — аргумент трактуется как целое и выводится в виде десятичного числа со знаком.
  • e — аргумент трактуется как число в научной нотации (например, 1.2e+2). Описатель точности указывает на количество знаков после запятой, начиная с версии PHP 5.2.1. В более ранних версиях он обозначал количество значащих цифр (на один знак меньше).
  • E — аналогично %e, но использует заглавную букву (например, 1.2E+2).
  • f — аргумент трактуется как число с плавающей точкой и также выводится в зависимости от локали.
  • F — аргумент трактуется как число с плавающей точкой и также выводится, но без зависимости от локали. Доступно, начиная с версии PHP 5.0.3.
  • g — выбирает самую краткую запись из %e и %f.
  • G — выбирает самую краткую запись из %E и %f.
  • o — аргумент трактуется как целое и выводится в виде восьмеричного числа.
  • s — аргумент трактуется как строка.
  • u — аргумент трактуется как целое и выводится в виде десятичного числа без знака.
  • x — аргумент трактуется как целое и выводится в виде шестнадцатеричного числа (в нижнем регистре).
  • X — аргумент трактуется как целое и выводится в виде шестнадцатеричного числа (в верхнем регистре).

Переменные будут преобразованы в соответвующий тип для спецификатора:

Обработка типов
Тип Спецификатор
string s
integer d, u, c, o, x, X, b
double g, G, e, E, f, F

Попытка использовать комбинацию строк и спецификаторов ширины с кодировками, которые требуют более одного байта на символ, может привести к неожиданным результатам.

В строке формата поддерживается нумерация и изменение порядка параметров. Например:

Пример #1 Изменение порядка параметров

= 5 ;
$location = ‘дереве’ ;

$format = ‘%d обезьян сидят на %s’ ;
echo sprintf ( $format , $num , $location );
?>

Пример #2 Изменение порядка параметров

Пример #3 Изменение порядка параметров

Пример #4 Изменение порядка параметров

Пример #5 Указание дополняющего символа

Результат выполнения данного примера:

Пример #6 Использование описателя позиции и совместно с другими описателями

Результат выполнения данного примера:

Попытка использовать спецификатор позиции, больший чем PHP_INT_MAX , приведет к генерации предупреждения функцией sprintf() .

Описатель типа c игнорирует дополнение строки и ее ширину

Возвращаемые значения

Возвращает строку, отформатированную в соответствии со строкой format , или FALSE в случае возникновения ошибки.

Примеры

Пример #7 sprintf() : заполнение нулями

= 43951789 ;
$u = — 43951789 ;
$c = 65 ; // ASCII 65 is ‘A’

// заметьте, двойной %% выводится как одинарный ‘%’
printf ( «%%b = ‘%b’\n» , $n ); // двоичное представление
printf ( «%%c = ‘%c’\n» , $c ); // выводит символ ascii, аналогично функции chr()
printf ( «%%d = ‘%d’\n» , $n ); // обычное целое число
printf ( «%%e = ‘%e’\n» , $n ); // научная нотация
printf ( «%%u = ‘%u’\n» , $n ); // беззнаковое целое представление положительного числа
printf ( «%%u = ‘%u’\n» , $u ); // беззнаковое целое представление отрицательного числа
printf ( «%%f = ‘%f’\n» , $n ); // представление числа с плавающей точкой
printf ( «%%o = ‘%o’\n» , $n ); // восьмеричное представление
printf ( «%%s = ‘%s’\n» , $n ); // строка
printf ( «%%x = ‘%x’\n» , $n ); // шестнадцатеричное представление (нижний регистр)
printf ( «%%X = ‘%X’\n» , $n ); // шестнадцатеричное представление (верхний регистр)

printf ( «%%+d = ‘%+d’\n» , $n ); // описатель знака с положительным целым числом
printf ( «%%+d = ‘%+d’\n» , $u ); // описатель знака с отрицательным целым числом
?>

Результат выполнения данного примера:

Пример #8 printf() : описатели строк

= ‘monkey’ ;
$t = ‘many monkeys’ ;

printf ( «[%s]\n» , $s ); // обычный вывод строки
printf ( «[%10s]\n» , $s ); // выравнивание вправо с пробелами
printf ( «[%-10s]\n» , $s ); // выравнивание влево с пробелами
printf ( «[%010s]\n» , $s ); // дополнение нулями также работает со строками
printf ( «[%’#10s]\n» , $s ); // использование собственного дополняющего символа ‘#’
printf ( «[%10.10s]\n» , $t ); // выравнивание влево с обрезкой в 10 символов
?>

Результат выполнения данного примера:

Пример #9 sprintf() : целые числа, дополненные нулями

Пример #10 sprintf() : форматирование денежных величин

Пример #11 sprintf() : научная нотация

echo sprintf ( «%.3e» , $number ); // выведет 3.625e+8
?>

Смотрите также

  • printf() — Выводит отформатированную строку
  • sscanf() — Разбирает строку в соответствии с заданным форматом
  • fscanf() — Обрабатывает данные из файла в соответствии с форматом
  • vsprintf() — Возвращает отформатированную строку
  • number_format() — Форматирует число с разделением групп
  • date() — Форматирует вывод системной даты/времени
Илон Маск рекомендует:  Некоторые функции win32
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL