Vprintf, vfprintf, vsprintf форматный вывод

Содержание

Vprintf, vfprintf, vsprintf форматный вывод

Печатает отформатированный вывод в стандартном потоке вывода данных (функция библиотеки С и С++).

Синтаксис

Параметры

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

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

Замечания

Функция printf форматирует и печатает ряд символов и значений в стандартном потоке вывода данных — stdout. Если параметры следуют за строкой format, то форматирующая (format) строка должна содержать спецификации, которые определяют формат вывода для параметров. Функции printf и fprintf ведут себя тождественно за исключением того, что printf печатает выводимые данные stdout, а не в целевой тип файла (FILE).

Функция wprintf — широкосимвольная версия printf (для Unicode); format — широкосимвольная строка. Функции wprintf и printf во всем остальном ведут себя тождественно.

Унифицированно-текстовые стандартные отображения

Стандартный TCHAR.H

_UNICODE & _MBCS не определен

_MBCS определен _unicode определен _tprintf printf printf wprintf

Параметр format состоит из обычных символов, последовательностей escape, и (если параметры следуют за параметром format), то спецификации формата. Обычные символы и последовательности escape копируются в stdout в порядке их поступления. Например, строка

Спецификации формата всегда начинаются со знака процента (%) и читается слева направо. Когда функция printf встречается с первой спецификацией формата (если она есть), то преобразует значение первого параметра после format и выводит его соответственно. Вторая спецификация формата заставляет второй параметр быть преобразованным и выведенным, и так далее. Если имеется больше параметров, чем есть их спецификаций, дополнительные параметры игнорируются. Результаты не определяются, если недостаточно параметров для всех спецификаций формата.

Поля спецификации формата: функции printf и wprintf

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

Каждое поле спецификации формата — это единичный символ или число, показывающее конкретный вариант выбора формата. Самая простая спецификация формата содержит в себе только знак процента и символ типа — type (например, %s). Если знак процента сопровождается символом, у которого нет никакого значения как поля формата, символ копируется в stdout. Например, чтобы напечатать символ знака процента, используйте %%.

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

Затребованный символ, который определяет, понимается ли связанный параметр как символ, строка или число (см. таблицу Поля типов символов printf.

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

Дополнительное число, которое указывает минимальное число выводимых символов (см. printf — Спецификация ширины).

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

Дополнительные префиксы для type, которые указывают размер параметра (см. таблицу Префиксы размера для printf и wprintf Спецификаторов типа формата).

Замечание по обеспечению безопасности! Убедитесь, что строки спецификации формата не определяемы пользователем. Например, рассмотрите программу, которая побуждает пользователя вводить свое имя и хранить вводимые данные в переменной строке, называемой name. Чтобы напечатать name, не делайте того, что ниже:

Вместо этого сделайте вот это:

Вывод данных

Смотри также

Процедуры поддержки плавающей запятой | Процедуры потоков ввода-вывода (I/O) | Локальные процедуры | функции fopen | fprintf | scanf | sprintf | vprintf | Процедуры времени исполнения программы и эквиваленты .NET Framework

Требования

Процедуры

Требуется заголовочный файл

Совместимость

printf ANSI, Win 98, Win Me, Win NT, Win 2000, Win XP
wprintf или ANSI, Win 98, Win Me, Win NT, Win 2000, Win XP

Дополнительную информацию о совместимости см. в статье Совместимость в главе Введение.

Библиотеки

Все версии библиотек времени исполнения программы C.

printf()

Вот прототип функции printf() :

Функция printf() возвращает число выведенных символов или отрицательное значение в случае ошибки.

Управляющая_строка [1] состоит из элементов двух видов. Первый из них — это символы, которые предстоит вывести на экран; второй — это спецификаторы преобразования [2] , которые определяют способ вывода стоящих за ними аргументов. Каждый такой спецификатор начинается со знака процента, за которым следует код формата. Аргументов должно быть ровно столько, сколько и спецификаторов, причем спецификаторы преобразования и аргументы должны попарно соответствовать друг другу в направлении слева направо. Например, в результате такого вызова printf()

В этом примере первому спецификатору преобразования ( %c ), соответствует символ ‘C’, а второму ( %s ), — строка «и к тому же очень сильно!».

В функции printf() , как видно из табл. 8.2, имеется широкий набор спецификаторов преобразования.

Таблица 8.2. Спецификаторы преобразования для функции printf()
Код Формат
%a Шестнадцатеричное в виде 0xh.hhhhp+d (только С99)
%A Шестнадцатеричное в виде 0Xh.hhhhP+d (только С99)
%c Символ
%d Десятичное целое со знаком
%i Десятичное целое со знаком
%e Экспоненциальное представление (‘е’ на нижнем регистре)
%E Экспоненциальное представление (‘Е’ на верхнем регистре)
%f Десятичное с плавающей точкой
%g В зависимости от того, какой вывод будет короче, используется %е или %f
%G В зависимости от того, какой вывод будет короче, используется %Е или %F
%o Восьмеричное без знака
%s Строка символов
%u Десятичное целое без знака
%x Шестнадцатеричное без знака (буквы на нижнем регистре)
%X Шестнадцатеричное без знака (буквы на верхнем регистре)
%p Выводит указатель
%n Аргумент, соответствующий этому спецификатору, должен быть указателем на целочисленную переменную. Спецификатор позволяет сохранить в этой переменной количество записанных символов (записанных до того места, в котором находится код %n )
%% Выводит знак %

Вывод символов

Для вывода отдельного символа используйте %с . В результате соответствующий аргумент будет выведен на экран без изменения.

Для вывода строки используйте %s .

Вывод чисел

Числа в десятичном формате со знаком отображаются с помощью спецификатора преобразования %d или %i . Эти спецификаторы преобразования эквивалентны; оба поддерживаются в силу сложившихся привычек программистов, например, из-за желания поддерживать те же спецификаторы, которые применяются в функции scanf() .

Для вывода целого значения без знака используйте %u .

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

Спецификаторы преобразования %e и %E в функции printf() позволяют отображать аргумент типа double в экспоненциальном формате. В общем виде числа в таком формате выглядят следующим образом:

Чтобы отобразить букву E в верхнем регистре, используйте спецификатор преобразования %E ; в противном случае используйте спецификатор преобразования %e .

Спецификатор преобразования %g или %G указывает, что функции printf() необходимо выбрать один из спецификаторов: %f или %e . В результате printf() выберет тот спецификатор преобразования, который позволяет сделать самый короткий вывод. Если нужно, чтобы при выборе экспоненциального формата буква E отображалась на верхнем регистре, используйте спецификатор преобразования %G ; в противном случае используйте спецификатор преобразования %g .

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

В результате выполнения получится следующее:

Целые числа без знака можно выводить в восьмеричном или шестнадцатеричном формате, используя спецификатор преобразования %o или %x . Так как в шестнадцатеричной системе для представления чисел от 10 до 15 используются буквы от А до F, то эти буквы можно выводить на верхнем или на нижнем регистре. Как показано ниже, в первом случае используется спецификатор преобразования %X , а во втором — спецификатор преобразования %x :

Вот что вывела эта программа:

Отображение адреса

Для отображения адреса используйте спецификатор преобразования %p . Этот спецификатор преобразования дает printf() указание отобразить машинный адрес в формате, совместимом с адресацией, которая используется компьютером. Следующая программа отображает адрес переменной sample :

Спецификатор преобразования %n

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

Программа отображает строку Это проверка , после которой появляется число 3 . Спецификатор преобразования %n в основном используется в программе для выполнения динамического форматирования.

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

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

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

Целое число, расположенное между знаком % и кодом формата, играет роль модификатора минимальной ширины поля . Если указан модификатор минимальной ширины поля, то чтобы ширина поля вывода была не меньше указанной минимальной длины, при необходимости вывод будет дополнен пробелами. Если же выводятся строки или числа, которые длиннее указанного минимума, то они все равно будут отображаться полностью. По умолчанию для дополнения используются пробелы. А если для этого надо использовать нули, то перед модификатором ширины поля следует поместить 0. Например, %05d означает, что любое число, количество цифр которого меньше пяти, будет дополнено таким количеством нулей, чтобы число состояло из пяти цифр. В следующей программе показано, как применяется модификатор минимальной ширины поля:

Вот что выводится при выполнении этой программы:

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

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

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

Когда модификатор точности применяется к данным с плавающей точкой, для преобразования которых используются спецификаторы преобразования %f , %e или %E , то он определяет количество выводимых десятичных разрядов. Например, %10.4f означает, что ширина поля вывода будет не менее 10 символов, причем для десятичных разрядов будет отведено четыре позиции.

Если модификатор точности применяется к %g или %G , то он определяет количество значащих цифр.

Примененный к строкам, модификатор точности определяет максимальную длину поля. Например, %5.7s означает, что длина выводимой строки будет составлять минимум пять и максимум семь символов. Если строка окажется длиннее, чем максимальная длина поля, то конечные символы выводиться не будут.

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

В следующей программе показано, как можно использовать модификатор точности:

Вот что выводится при выполнении этой программы:

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

По умолчанию весь вывод выравнивается по правому краю. То есть если ширина поля больше ширины выводимых данных, то эти данные располагаются по правому краю поля. Вывод по левому краю можно назначить принудительно, поместив знак минус прямо за % . Например, %-l0.2f означает, что число с плавающей точкой и с двумя десятичными разрядами будет выровнено по левому краю 10-символьного поля.

В следующей программе показано, как применяется выравнивание по левому краю:

И вот что получилось:

Обработка данных других типов

Некоторые модификаторы в вызове функции printf() позволяют отображать целые числа типа short и long . Такие модификаторы можно использовать для следующих спецификаторов типа: d , i , o , u и x . Модификатор l (эль) в вызове функции printf() указывает, что за ним следуют данные типа long . Например, %ld означает, что надо выводить данные типа long int . После модификатора h функция printf() выведет целое значение в виде short . Например, %hu означает, что выводимые данные имеют тип short unsigned int .

Модификаторы l и h можно также применить к спецификатору n . Это делается с той целью, чтобы показать — соответствующий аргумент является указателем соответственно на длинное ( long ) или короткое ( short ) целое.

Если компилятор поддерживает обработку символов в расширенном 16-битном алфавите, добавленную Поправкой 1 от 1995 года (1995 Amendment 1), то для указания символа в расширенном 16-битном алфавите вы можете применять модификатор 1 для спецификатора преобразования c . Кроме того, для указания строки из символов в расширенном 16-битном алфавите можно применять модификатор 1 для спецификатора преобразования s .

Модификатор L может находиться перед спецификаторами преобразования с плавающей точкой e , f и g , и указывать этим, что преобразуется значение long double .

В Стандарте С99 вводится два новых модификатора формата: hh и ll . Модификатор hh можно применять для спецификаторов преобразования d , i , o , u , x или n . Он показывает, что соответствующий аргумент является значением signed или unsigned char или, в случае n , указателем на переменную signed char . Модификатор ll также можно применять для спецификаторов преобразования d , i , o , u , x или n . Он показывает, что соответствующий аргумент является значением signed или unsigned long long int или, в случае n , указателем на long long int . В С99 также разрешается применять l для спецификаторов преобразования с плавающей точкой a , е , f и g ; впрочем, это не дает никакого результата.

На заметку В составе С99 имеются некоторые дополнительные модификаторы типа для функции printf() ; о них рассказывается в части II.

Модификатор * и #

Для некоторых из своих спецификаторов преобразования функция printf() поддерживает два дополнительных модификатора: * и # .

Непосредственное расположение # перед спецификаторами преобразования g , G , f , Е или e означает, что при выводе обязательно появится десятичная точка — даже если десятичных цифр нет. Если вы поставите # непосредственно перед x или X , то шестнадцатеричное число будет выведено с префиксом 0x . Если # будет непосредственно предшествовать спецификатору преобразования o , число будет выведено с ведущим нулем. К любым другим спецификаторам преобразования модификатор # применять нельзя. (В С99 модификатор # можно применять по отношению к преобразованию %а ; это значит, что обязательно будет выведена десятичная точка.)

Модификаторы минимальной ширины поля и точности можно передавать функции printf() не как константы, а как аргументы. Для этого в качестве заполнителя используйте звездочку ( * ). При сканировании строки формата функция printf() будет каждой звездочке * из этой строки ставить в соответствие очередной аргумент, причем в том порядке, в каком расположены аргументы. Например, при выполнении оператора, показанного на рис. 8.1, минимальная ширина поля будет равна 10 символам, точность — 4, а отображаться будет число 123.3 .

В следующей программе показано применение обоих модификаторов # и * :

Рис. 8.1. Обратите внимание на то, каким образом звездочке (*) ставится в соответствие определенное значение

[1] Часто называется просто форматной строкой , форматным стрингом или форматом .

[2] Называются также спецификациями формата .

[3] Называются также спецификаторами .

Форматированный вывод. Функция 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 . Об этом мы поговорим в следующем уроке.

Форматный ввод-вывод: функции fscanf и fprintf

В отличие от функции бинарного ввода fread, которая вводит байты из файла без всякого преобразования непосредственно в память компьютера, функция форматного ввода fscanf предназначена для ввода информации с преобразованием ее из текстового представления в бинарное. Пусть информация записана в текстовом файле в привычном для человека виде (т.е. так, что ее можно прочитать или ввести в файл, используя текстовый редактор). Функция fscanf читает информацию из текстового файла и преобразует ее во внутреннее представление данных в памяти компьютера. Информация о количестве читаемых элементов, их типах и особенностях представления задается с помощью формата. В случае функции ввода формат — это строка, содержащая описания одного или нескольких вводимых элементов. Форматы, используемые функцией fscanf, аналогичны применяемым функцией scanf, они уже неоднократно рассматривались (см. раздел 3.5.4). Каждый элемент формата начинается с символа процента «%». Наиболее часто используемые при вводе форматы приведены в таблице:

целое десятичное число типа int (d — от decimal)

вещ. число типа double (lf — от long float)

один символ типа char

ввод строки. Из входного потока выделяется слово, ограниченое пробелами или символами перевода строки ‘\n’. Слово помещается в массив символов. Конец слова отмечается нулевым байтом.

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

int fscanf(FILE *f, const char *format, . );

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

int n, m; double a; char c; char str[256];

fscanf(f, «%d», &n); // Ввод целого числа

fscanf(f, «%lf», &a); // Ввод вещественного числа

fscanf(f, «%c», &c); // Ввод одного символа

fscanf(f, «%s», str); // Ввод строки (выделяется очередное

// слово из входного потока)

fscanf(f, «%d%d», &n, &m); // Ввод двух целых чисел

Функция fscanf возвращает число успешно введенных элементов. Таким образом, возвращаемое значение всегда меньше или равно количеству процентов внутри форматной строки (которое равно числу фактических аргументов минус 2).

Функция fprintf используется для форматного вывода в файл. Данные при выводе преобразуются в их текстовое представление в соответствии с форматной строкой. Ее отличие от форматной строки, используемой в функции ввода fscanf, заключается в том, что она может содержать не только форматы для преобразования данных, но и обычные символы, которые записываются без преобразования в файл. Форматы, как и в случае функции fscanf, начинаются с символа процента «%». Они аналогичны форматам, используемым функцией fscanf. Небольшое отличие заключается в том, что форматы функции fprintf позволяют также управлять представлением данных, например, указывать количество позиций, отводимых под запись числа, или количество цифр после десятичной точки при выводе вещественного числа. Некоторые типичные примеры форматов для вывода приведены в следующей таблице:

вывод целого десятичного числа

вывод целого десятичного числа, для записи числа отводится 10 позиций, запись при необходимости дополняется пробелами слева

вывод вещественного число типа double в форме с фиксированной десятичной точкой

вывод вещественного число типа double с печатью трёх знаков после десятичной точки

вывод вещественного число типа double с тремя знаками после десятичной точки, под число отводится 12 позиций

вывод одного символа

конец строки, т.е. массива символов. Конец строки задается нулевым байтом

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

int fprinf(FILE *f, const char *format, . );

Многоточие, как и в случае функции fscanf, означает, что функция имеет переменное число аргументов. Количество и типы аргументов, начиная с третьего, должны соответствовать форматной строке. В отличие от функции fscanf, фактические аргументы, начиная с третьего, представляют собой выводимые значения, а не указатели на переменные. Для примера рассмотрим небольшую программу, выводящую данные в файл «tmp.dat»:

#include // Описания функций ввода вывода

#include // Описания математических функций

#include // Описания функций работы со строками

int n = 4, m = 6; double x = 2.;

char str[256] = «Print test»;

FILE *f = fopen(«tmp.dat», «wt»); // Открыть файл

perror(«Не могу открыть файл для записи»);

return 1; // Завершить программу с кодом ошибки

fprintf(f, «n=%d, m=%d\n», m, n);

fprintf(f, «x=%.4lf, sqrt(x)=%.4lf\n», x, sqrt(x));

f, «Строка \»%s\» содержит %d символов.\n»,

fclose(f); // Закрыть файл

return 0; // Успешное завершение программы

В результате выполнения этой программы в файл «tmp.dat» будет записан следующий текст:

Строка «Print test» содержит 10 символов.

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

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, описание выходных данных:

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

Vprintf, vfprintf, vsprintf форматный вывод

Уже Фортран I имел операторы, обеспечивавшие форматный вывод. Синтаксис операторов WRITE и PRINT предусматривал метку, отсылающую к неисполняемому оператору FORMAT, который содержал форматную спецификацию. Спецификаторы были частью синтаксиса оператора, и компилятор сразу мог сформировать код, непосредственно выполняющий форматирование данных, что обеспечивало наилучшую производительность на вычислительных машинах тех времён. Однако имелись следующие недостатки:

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

Первый прототип будущей функции printf появляется в языке 1960-х. Функция WRITEF принимает строку форматирования, в которой тип данных указывается отдельно от самих данных в строковой переменной (тип указывался без полей флагов, ширины, точности и размера, но уже предварялся символом процента % ). [1] Основной целью появления строки форматирования была передача типов аргументов (в языках программирования со статической типизацией определение типа переданного аргумента для функции с нефиксированным списком формальных параметров требует сложного и неэффективного для общего случая механизма передачи информации о типах). Сама функция WRITEF была средством упрощения вывода: вместо набора функций WRCH (вывод символа), WRITES (вывод строки), WRITEN, WRITED, WRITEOCT, WRITEHEX (вывод чисел в различной форме) использовался единый вызов, в котором можно было чередовать «просто текст» с выходными значениями.

Си и производные

С момента появления первого варианта языка Си (1970) семейство printf стало основным средством форматного вывода. Затраты на разбор форматной строки при каждом вызове функции были сочтены приемлемыми, и альтернативные вызовы для каждого типа в отдельности в библиотеку введены не были. Спецификация функции вошла в оба существующих стандарта языка, вышедших в 1990 и 1999 годах. Спецификация 1999 года содержит некоторые нововведения по отношению к спецификации 1990 года.

Язык Си++ использует стандартную библиотеку Си (в соответствии со стандартом 1990 года), в том числе и всё семейство printf.

В качестве альтернативы стандартная библиотека Си++ предложила набор классов потокового ввода и вывода. Операторы вывода этой библиотеки типобезопасны и не требуют разбора форматных строк при каждом вызове. Тем не менее, многие программисты продолжают пользоваться семейством printf, так как запись последовательности вывода с ними обычно оказывается компактнее, а суть применяемого формата — яснее.

Использование в других языках программирования

Помимо Си и его производных (Си++, Objective-C), printf-подобный синтаксис строки форматирования используют многие другие языки программирования:

Помимо этого, благодаря наличию утилиты printf в составе большинства UNIX-подобных систем, printf используется во многих shell-скриптах (для

Последователи

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

Например, в основной библиотеке классов (FCL) среды .Net имеется семейство методов System.String.Format, System.Console.Write и System.Console.WriteLine, некоторые перегрузки которых выполняют вывод своих данных в соответствии с форматной строкой. Так как в среде исполнения .Net доступна полная информация о типах объектов, необходимости передавать эту информацию в форматной строке нет.

Именование функций семейства

Все функции имеют в имени основу printf. Префиксы перед именем функции означают:

  • v (vprintf, vsnprintf и т.д.) — функция вместо переменного числа параметров принимает список аргументов va list.
  • f (fprintf, vfprintf) — вывод результата в передаваемый через параметр функции поток, вместо стандартного вывода.
  • s (sprintf, snprintf, vsprintf, vspnprintf) — запись результата в строку (буфер в памяти), а не поток.
  • n (snprintf, vnsprintf) — наличие параметра, ограничивающего максимальное количество символов для записи результата (используется только вместе с префиксом s). В Maple функция nprintf аналогична sprintf, но возвращает не текстовую строку, а имя.
  • w, перед остальными префиксами (wsprintf, wvsprintf, wnsprintf, wvnsprintf) — использующийся фирмой sprintf в операционных системах Windows.
  • w, после остальных префиксов (fwprintf, swprintf, wprintf) — функция использует многобайтовую кодировку (wchar_t) вместо обычных строк. (при этом функция swprintf не имеет префикса «n», хотя и принимает параметр, ограничивающий размер результирующей строки).
  • a (asprintf, vasprintf) — расширения malloc для форматированной строки. Вместо указателя на строку эти функции принимают указатель на указатель на строку, освобождение памяти производит вызвавшая функция.

Общие соглашения

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

Функции семейства n (snprintf, vsnprintf) возвращают количество символов, которое было бы выведено, если бы параметр n (ограничивающий количество выводимых символов) был достаточно большим. В случае однобайтовых кодировок, возвращаемое значение соответствует необходимому размеру строки (не включая нулевой символ в конце).

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

Функции семейства f записывают строку в любой открытый поток (параметр stream), в частности, в стандартные потоки вывода (stdout, stderr). fprintf(stdout, format, …) эквивалентно printf(format, …) .

Функции семейства v принимают аргументы не в виде переменного числа аргументов (как все остальные printf-функции), а в виде списка va list. При этом при вызове функции макрос va end не выполняется.

Функции семейства w (первым символом) являются ограниченной реализацией Microsoft семейства функций s: wsprintf, wnsprintf, wvsprintf, wvnsprintf. Эти функции реализованы в динамических библиотеках user32.dll и shlwapi.dll (n функции). Они не поддерживают вывод значений с плавающей запятой, кроме того, wnsprintf и wvnsprintf поддерживают выравнивание текста только по левому краю.

Функции семейства w (wprintf, swprintf) реализуют поддержку многобайтовых кодировок, все функции этого семейства работают с указателями на многобайтные строки (wchar_t).

Функции семейства a (asprintf, vasprintf) выделяют память для строки вывода при помощи функции

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

Имена параметров

  • format — строка форматирования (формат описан ниже)
  • stream — файловый поток для вывода
  • s — строка для помещения результата работы функции
  • n — переменная, содержащая максимальное допустимое количество символов для строки s
  • ap — список значений для вывода
  • strp — указатель на указатель на строку для помещения результатов работы функции

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

  • int printf( const char *format, . ); Вывод форматированной строки на стандартный вывод
  • int fprintf( FILE *stream, const char *format, . ); Вывод форматированной строки в поток
  • int sprintf( char *s, const char *format, . ); Запись форматированной строки в строку без ограничения по размеру строки
  • int snprintf( char *s, size_t n, const char *format, . ); Запись форматированной строки в строку с ограничением по размеру строки
  • int vprintf( const char *format, va_list ap ); Вывод форматированной строки на стандартный вывод, значения для вывода передаются в функцию в виде списка va list
  • int vfprintf( FILE *stream, const char *format, va_list ap ); Запись форматированной строки в поток, значения для вывода передаются в функцию в виде списка va list
  • int vsprintf( char *s, const char *format, va_list ap ); Запись форматированной строки в строку без ограничения размера; значения для вывода передаются в функцию в виде списка va list
  • int vsnprintf( char *s, size_t n, const char *format, va_list ap ); Запись форматированной строки в строку с ограничением на количество выводимых символов. Значения для вывода передаются в функцию в виде списка va list
  • int fwprintf(FILE *stream, const wchar_t *format, . ); Запись форматированной строки многобайтовых символов в файл
  • int swprintf(wchar_t *ws, size_t n, const wchar_t *format, . ); Запись форматированной многобайтовой строки в область памяти (Примечание: несмотря на отсутствие буквы n в названии, эта функция принимает параметр, ограничивающий максимальный размер выходной строки).
  • int wprintf(const wchar_t *format, . ); Вывод многобайтовой форматированной строки на терминал
  • int wsprintf( LPTSTR s, LPCTSTR format, . ); Реализация функции sprintf в операционной системе Windows. В отличие от sprintf не поддерживает вывод значений с плавающей запятой, вывод указателей, дополнительно поддерживает обработку многобайтовых строк в однобайтовой версии функции), не поддерживает флаг '+'.
  • int wnsprintf( LPTSTR s, int n, LPCTSTR format, . ); Реализация функции snprintf в операционной системе Windows. Не поддерживает вывод значений с плавающей запятой и указателей, поддерживает только флаг выравнивания по левому краю.
  • int wvsprintf( LPTSTR s, LPCTSTR format, va_list ap );
  • int wvnsprintf( LPTSTR s, int n, LPCTSTR format, va_list ap );
  • int asprintf(char **strp, const char *format, . ); функция записывает результат в строку, память для которой выделяется при помощи функция записывает результат в строку, память для которой выделяется при помощи

Возвращаемое значение: отрицательное значение - признак ошибки; в случае успеха функции возвращают количество записанных/выведенных байтов (без учёта нулевого байта в конце), функция snprintf выводит количество байт, которые были бы записаны, если бы n было бы достаточного размера.

При вызове snprintf, n может быть равно нулю (в этом случае s может быть нулевым указателем), в этом случае запись не производится, функция только возвращает правильное возвращаемое значение.

Синтаксис строки форматирования

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

Структура управляющей последовательности

Управляющая последовательность имеет вид:

Обязательными составными частями являются символ начала управляющей последовательности ( % ) и тип.

Флаги

Знак Название знака Значение В отсутствие этого знака Примечание
- дефис выводимое значение выравнивается по левому краю в пределах минимальной ширины поля по правому
+ плюс всегда указывать знак (плюс или минус) для выводимого десятичного числового значения только для отрицательных чисел
пробел помещать перед результатом пробел, если первый символ значения не знак Вывод может начинаться с цифры. Символ + имеет больший приоритет, чем пробел. Используется только для десятичных числовых значений.
# октоторп «альтернативная форма» вывода значения см. ниже
ноль дополнять поле до ширины, указанной в поле ширина управляющей последовательности, символом 0 дополнять пробелами Используется для типов d, i, o, u, x, X, a, A, e, E, f, F, g, G. Для типов d, i, o, u, x, X, если точность указана, этот флаг игнорируется. Для остальных типов поведение не определено.

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

Ширина (десятичное число или символ звёздочка) указывает минимальную ширину поля (включая знак для чисел). Если представление величины больше, чем ширина поля, то запись выходит за пределы поля (например, %2i для величины 100 даст значение поля в три символа), если представление величины менее указанного числа, то оно будет дополнено, по-умолчанию, пробелами справа, поведение может меняться предшествующими флагами. Если в качестве ширины указана звёздочка, ширина поля указывается в списке аргументов перед значением для вывода (например, printf( "%0*x", 8, 15 ); выведет текст 0000000f ).

Спецификатор точности

  • указывает на минимальное количество символов, которое должно появиться при обработке типов d, i, o, u, x, X;
  • указывает на минимальное количество символов, которое должно появиться после десятичной запятой (точки) при обработке типов a, A, e, E, f, F;
  • максимальное количество значащих символов для типов g и G;
  • максимальное число символов, которые будут выведены для типа s;

Точность задаётся в виде точки с последующим десятичным числом или звёздочкой (*), если число или звёздочка отсутствует (присутствует только точка), то предполагается, что число равно нулю. Точка для указания точности используется даже в том случае, если при выводе чисел с плавающей запятой выводится запятая.

Если после точки указан символ «звёздочка», то при обработке строки форматирования значение для поля читается из списка аргументов. (При этом, если символ звёздочка и в поле ширины и в поле точности, сначала указывается ширина, потом точность и лишь потом значение для вывода). Например, printf( "%0*.*f", 8, 4, 2.5 ); выведет текст 002.5000 .

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

Поле размер позволяет указать размер данных, переданных функции. Необходимость в этом поле объясняется особенностями передачи произвольного количества параметров в функцию в языке Си: функция не может «самостоятельно» определить тип и размер переданных данных, так что информация о типе параметров и точном их размере должна передаваться явно.

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

Знаковый тип Беззнаковый тип
signed char unsigned char
signed short (short) unsigned short int (unsigned short)
signed int (int) unsigned int (unsigned)
signed long int (long) unsigned long int (unsigned long)
signed long long int (long long) unsigned long long int (unsigned long long)

Точные размеры типов неизвестны за исключением типов signed char и unsigned char.

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

Тип char имеет одинаковый размер с типами signed char и unsigned char и общий набор представимых значений с одним из этих типов. Далее считается, что char — другое имя одного из этих типов; такое допущение приемлемо для настоящего рассмотрения.

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

Кроме того, в языке Си присутствует тип _Bool, а в Си++ — bool.

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

  • аргументы типа float приводятся к типу double;
  • аргументы типов unsigned char, unsigned short, signed char и short приводятся к одному из следующих типов:
    • int, если этот тип способен представить все значения исходного типа, или
    • unsigned в противном случае;
  • аргументы типов _Bool или bool приводятся к типу int.

Таким образом, функции printf не могут получать аргументов типов float, _Bool или bool или целочисленных типов меньших, чем int или unsigned.

Набор применяемых спецификаторов размера зависит от спецификатора типа (см. ниже).

Спецификатор %d , %i , %o , %u , %x , %X %n Примечание
отсутствует int или unsigned int указатель на int
l long int или unsigned long int указатель на long int
hh Аргумент имеет тип int или unsigned int, но принудительно приводится к типу signed char или unsigned char, соответственно указатель на signed char формально существуют только в языке Си начиная со второго стандарта (1999)
h Аргумент имеет тип int или unsigned int, но принудительно приводится к типу short int или unsigned short int, соответственно указатель на short int
ll long long int или unsigned long long int указатель на long long int
j intmax_t или uintmax_t указатель на intmax_t
z size_t (или эквивалентный по размеру знаковый тип) указатель на эквивалентный по размеру size_t знаковый тип
t ptrdiff_t (или эквивалентный по размеру беззнаковый тип) указатель на ptrdiff_t

Спецификации h и hh используются для компенсации стандартных продвижений типов в сочетании с переходами от знаковых типов к беззнаковым или наоборот.

Например, рассмотрим реализацию Си, где тип char знаковый и имеет размер 8 бит, тип int имеет размер 32 бит, используется дополнительный способ кодирования отрицательных целых.

Такой вызов даст вывод FFFFFFFF , что, возможно, не то, чего ожидал программист. Действительно, значение c равно (char)(-1), а после продвижения типа оно оказывается равно -1. Применение формата %X вызывает интерпретацию данного значения как беззнакового, то есть, 0xFFFFFFFF.

Эти два вызова имеют один и тот же эффект и дают вывод FF . Первый вариант позволяет избежать размножения знака при продвижении типа, второй — компенсирует его уже «внутри» функции printf.

Спецификатор %a , %A , %e , %E , %f , %F , %g , %G
отсутствует double
L long double
Спецификатор %c %s
отсутствует Аргумент имеет тип int или unsigned int, но принудительно приводится к типу char char*
l Аргумент имеет тип wint_t, но принудительно приводится к типу wchar_t wchar_t*

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

Тип указывает не только на тип величины (с точки зрения языка программирования Си), но и на конкретное представление выводимой величины (например, числа могут выводить в десятичном или шестнадцатеричном виде). Записывается в виде одного символа. В отличие от остальных полей является обязательным. Максимальный поддерживаемый размер вывода от единичной управляющей последовательности составляет по стандартам как минимум 4095 символов; на практике большинство компиляторов поддерживают существенно большие объёмы данных.

  • d, i — десятичное знаковое число, размер по-умолчанию, sizeof( int ). По-умолчанию записывается с правым выравниванием, знак пишется только для отрицательных чисел;
  • o — восьмеричное беззнаковое число, размер по-умолчанию sizeof( int );
  • u — десятичное беззнаковое число, размер по-умолчанию sizeof( int );
  • x и X — шестнадцатеричное число, x использует маленькие буквы (abcdef), X большие (ABCDEF), размер по-умолчанию sizeof( int );
  • f и F — числа с плавающей запятой. По-умолчанию выводятся с точностью 6, если число по модулю меньше единицы, перед десятичной точкой пишется 0. Величины ±∞ представляются в форме [-]inf или [-]infinity, Величина Nan представляется как [-]nan или [-]nan(любой текст далее). Использование F выводит указанные величины заглавными буквами (-INF, NAN). Аргумент по-умолчанию имеет размер double.
  • e и E — числа с плавающей запятой в экспоненциальной форме записи (вида 1.1e+44); e выводит символ «e» в нижнем регистре, E — в верхнем (3.14E+0);
  • g и G — число с плавающей запятой; форма представления зависит от значения величины (f или e);
  • a и A — число с плавающей запятой в шестнадцатеричном виде;
  • c — вывод символа с кодом, соответствующим переданному аргументу; переданное число приводится к типу unsigned char (или wint t, если был указан модификатор длины l);
  • s — вывод строки с нулевым завершающим байтом; если модификатор длины - l, выводится строка wchar_t*;
  • p — вывод указателя, внешний вид может существенно различаться в зависимости от внутреннего представления в компиляторе и платформе (например, 16 битная платформа MS-DOS использует форму записи вида FFEC:1003 , 32-битная платформа с плоской адресацией использует адрес вида 00FA0030 );
  • n — запись по указателю, переданному в качестве аргумента, количества символов, записанных на момент появления командной последовательности, содержащей n;
  • % — символ для вывода знака процента (%), используется для возможности вывода символов процента в строке printf, всегда используется в виде %% .
Вывод чисел с плавающей запятой

В зависимости от текущей локали, при выводе чисел с плавающей запятой может использоваться как запятая, так и точка (а, возможно, и другой символ). Поведение printf в отношении разделяющего дробную и целую часть числа символа определяется использующейся локалью (точнее, переменной LC NUMERIC). [14]

Специальные макросы для расширенного набора псевдонимов целочисленных типов данных

Второй стандарт языка Си (1999) предусматривает расширенный набор псевдонимов целочисленных типов данных intN_t, uintN_t, int_leastN_t, uint_leastN_t, int_fastN_t, uint_fastN_t (где N — требуемая разрядность), intptr_t, uintptr_t, intmax_t, uintmax_t.

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

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

Имена макросов имеют следующий вид:

Пара знакового и беззнакового типов Имя макроса
intN_t и uintN_t PRITN
int_leastN_t и uint_leastN_t PRITLEASTN
int_fastN_t и uint_fastN_t PRITFASTN
intmax_t и uintmax_t PRITMAX
intptr_t и uintptr_t PRITPTR

Здесь T — одна из следующих спецификаций типа: d , i , u , o , x , X .

Можно заметить, что для типов intmax_t и uintmax_t имеется стандартный спецификатор размера j , поэтому макрос PRITMAX , скорее всего, всегда определён как "jT" .

XSI расширения в стандарте Single Unix

Нестандартные расширения

GNU C Library

В рамках GNU C Library (libc) добавлены следующие расширения:

  • типm выводит значение глобальной переменной errno (код ошибки последней функции).
  • типC эквивалентен lc.
  • флаг' (одинарная кавычка) используется для разделения классов при выводе чисел. Формат разделения зависит от LC_NUMERIC
  • размерq указывает на тип long long int (на системах, где не поддерживается тип long long int, это то же самое, что и long int
  • размерZ является псевдонимом для z, был введён в libc до появления стандарта
Регистрация собственных типов

GNU libc поддерживает регистрацию пользовательских типов, позволяя программисту определять формат вывода для собственных структур данных. Для регистрации нового типа используется функция
int register_printf_function (int type, printf_function handler-function, printf_arginfo_function arginfo-function) , где:

  • type — буква для типа (если type = 'Y', то вызов будет выглядеть как '%Y');
  • handler-function — указатель на функцию, которая вызывается, printf-функциями, если в строке форматирования встречается тип, указанный в type;
  • arginfo-function — указатель на функцию, которая будет вызываться функцией parse_printf_format.

Помимо определения новых типов регистрация позволяет переопределить существующие типы (такие, как s, i).

Microsoft Visual C

В составе Microsoft Visual Studio для языков программирования Си/Си++ в формате спецификации printf (и остальных функций семейства) предусмотрены следующие расширения:

  • поле размера:
значение поля тип
I32 signed __int32, unsigned __int32
I64 signed __int64, unsigned __int64
I ptrdiff_t, size_t
w эквивалентно l для строк и символов

Maple

В среде математических вычислений Maple также имеется функция printf, она имеет следующие особенности:

Форматирование
    • %a, %A: объект Maple будет выдан в текстовой нотации, это работает для всех объектов (например, матриц, функций, модулей и т. д.). Строчная буква предписывает окружать обратными апострофами символы (имена), которые должны быть окружены ими на входе printf.
    • %q, %Q: то же, что и %a/%A, но обрабатываться будет не один аргумент, а все начиная с того, которому соответствует флаг форматирования. Таким образом, флаг %Q/%q может стоять только последним в строке формата.
    • %m: форматировать объект в соответствии с его внутренним для maple представлением. Практически используется для записи переменных в файл.
Вывод

Функция fprintf в maple в первом аргументе принимает либо дескриптор файла (возвращаемый функцией fopen), либо имя файла. В последнем случае имя должно имет тип "символ", если имя файла содержит точки, то его обязательно нужно заключить в обратные апострофы или преобразовать функцией convert(имя_файла, symbol).

Уязвимости

Функции семейства printf принимают список аргументов и их размер отдельным параметром (в строке форматирования). Несоответствие строки форматирования и переданных аргументов может приводить к непредсказуемому поведению, повреждению стека и выполнению произвольного кода, приводить к разрушению областей динамической памяти. Многие функции семейства называются «небезопасными» (англ. unsafe ), так как не имеют даже теоретической возможности для защиты от некорректных данных.

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

Поведение при несоответствии строки форматирования и переданных аргументов

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

  • количество и тип аргументов совпадают с указанными в строке форматирования (нормальная работа функции)
  • в функцию передано больше аргументов, чем указано в строке форматирования (лишние аргументы)
  • в функцию передано меньше аргументов, чем требуется согласно строке форматирования (недостаток аргументов)
  • в функцию переданы аргументы неправильного размера
  • в функцию переданы аргументы правильного размера но неправильного типа

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

Избыточное количество аргументов

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

Недостаточное количество аргументов

Если при вызове printf аргументов в стеке меньше, чем требуется для обработки строки форматирования, то недостающие аргументы читаются со стека, несмотря на то, что на стеке находятся произвольные данные (не имеющие отношения к работе printf). Если обработка данных прошла «успешно» (то есть не привела к прекращению работы программы, зависанию или записи в стек), после возврата в вызывающую функцию значение указателя стека возвращается в исходное, и работа программы продолжается.

При обработке «лишних» значений стека, возможны следующие ситуации:

  • успешное чтение «лишнего» параметра для вывода (число, указатель, символ и т. д.) — в результаты вывода помещается «почти случайное» значение, прочитанное со стека. Это не представляет из себя опасности для работы программы, но может приводить к компрометации каких-либо данных (вывод значений стека, которые может использовать злоумышленник для анализа работы программы и получению доступа к внутренней/закрытой информации программы).
  • ошибка при чтении значения со стека (например, в результате исчерпания доступных значений стека или доступ к «несуществующим» страницам памяти) — такая ошибка вероятнее всего приведёт к аварийному завершению работы программы.
  • чтение указателя на параметр. Строки передаются с помощью указателя, при чтении «произвольной» информации со стека, прочитанное (почти случайное) значение используется как указатель на случайную область памяти. Поведение программы в этом случае не определено и зависит от содержимого этой области памяти.
  • запись параметра по указателю ( %n ) — в данном случае поведение аналогично ситуации с чтением, но осложняется возможными сторонними эффектами записи в произвольную ячейку памяти.

Несоответствие типов аргументов

Формально любое несоответствие типа аргумента ожиданию вызывает неопределённое поведение программы. На практике можно выделить несколько особо интересных с точки зрения программистской практики случаев:

  • Аргумент имеет тот же тип, что и ожидается, но другой размер.
  • Аргумент имеет тот же размер, что и ожидается, но другой тип.

Иные случаи, как правило, приводят к очевидно некорректному поведению, и легко выявляются.

Несоответствие размера целочисленного или аргумента или аргумента с плавающей точкой

Для целочисленного аргумента (при целочисленной же форматной спецификации) возможны следующие ситуации:

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

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

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

Выравнивание значений на стеке

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

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

Потенциальное несоответствие размеров

Определения языков Си и Си++ описывают лишь наиболее общие требования к размерам и представлению типов данных. Поэтому на многих платформах представление некоторых формально разных типов данных оказываются одинаковыми. Это приводит к тому, что некоторые несовпадения типов могут долгое время оставаться необнаружимыми.

Например, на платформе Win32 общепринято, что размеры типов int и long int совпадают (32 разряда). Так, вызов printf("%ld", 1) или printf("%d", 1L) будет выполнен «правильно».

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

При написании программ на языке Си++ нужно внимательно относиться к выводу значений переменных, объявленных при помощи псевдонимов целочисленных типов, в частности size_t и ptrdiff_t ; формальное определение стандартной стандартной библиотеки Си++ ссылается на первый стандарт языка Си (1990). Во втором стандарте языка Си (1999) для типов size_t и ptrdiff_t и для ряда иных типов определены спецификаторы размера для использования с подобными объектами. Многие реализации Си++ их также поддерживают.

Несоответствие типов при совпадении размеров

Если переданные аргументы совпадают по размеру, но имеют отличный тип, то часто работа программы будет «почти правильной» (не вызовет ошибок доступа к памяти), хотя выводимое значение, вероятнее всего, будет бессмысленным. Надо отметить, что смешение па́рных друг другу целочисленных типов (знакового и беззнакового) допустимо, неопределённого поведения не вызывает, и иногда сознательно используется в практике.

При использовании форматной спецификации %s значение аргумента целочисленного, вещественного типа или типа указателя иного нежели char* , будет проинтерпретировано как адрес строки. Этот адрес, вообще говоря, может произвольно указывать на несуществующую или недоступную область памяти, что приведёт к ошибке доступа к памяти, либо на область памяти, не содержащую строки, что приведёт к выводу бессмыслицы, возможно, очень объёмному.

Уязвимость строки форматирования

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

Пример некорректного кода:
printf(" Current status: 99 % stored.");
В этом примере содержится управляющая последовательность «% s», содержащая признак управляющей последовательности (%), флаг (пробел) и тип данных «строка» (s). Функция, приняв управляющую последовательность, попытается прочитать из стека указатель на строку. Так как функции не передавались дополнительные параметры, значение, которое будет прочитано со стека, не определено. Полученное значение будет интерпретировано как указатель на строку с завершающим нулём. Вывод такой «строки» может привести к выводу произвольного дампа памяти, ошибке доступа к памяти и разрушению стека. Такой тип уязвимости называют атакой на строку форматирования (англ. Format string attack ). [15]

Переполнение буфера

Функция printf при выводе результата не ограничивается по максимальному количеству выводимых символов. Если в результате ошибки или недосмотра будет выведено больше символов, чем ожидалось, худшее, что может случиться — это «разрушение» картинки на экране. Созданная по аналогии с printf функция sprintf также не ограничивалась в максимальном размере результирующей строки. Однако в отличие от «бесконечного» терминала, память, которую выделяет приложение для результирующей строки, всегда ограничена. И в случае выхода за ожидаемые рамки, запись производится в области памяти, принадлежащие другим структурам данных (или, вообще, в недоступные участки памяти, что практически на всех платформах означает аварийное завершение программы). Запись в произвольные области памяти приводит к непредсказуемым эффектам (которые, возможно, проявятся много позже и не в форме ошибки программы, а в форме повреждения пользовательских данных). Отсутствие ограничения на максимальный размер строки является принципиальной ошибкой планирования при разработке функции. Именно из-за этого функции sprintf и vsprintf имеют статус небезопасных. Взамен им были разработаны функции snprintf, vsnprintf, принимающие дополнительный аргумент, ограничивающий максимальную результирующую строку. Появившаяся много позже функция swprintf (для работы с многобайтными кодировками) учитывает эту недоработку и принимает аргумент для ограничения результирующей строки. (Именно поэтому нет функции snwprintf).

Пример опасного вызова sprintf:

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

Сложности в использовании

Функции семейства printf используют типы данных языка Си, размер типов, и соотношение размеров типов может меняться от платформы к платформе (например, на 64-битных платформах в зависимости от выбранной модели (LP64, LLP64 или ILP64) размеры типов int и long могут различаться). При этом "правильно" работавший код на одной платформе начинает выдавать неправильный результат на другой (в ряде случаев, возможно, приводя к повреждению данных).

Например, код printf( "text address: 0x%X", "text line" ); работает правильно на 32-битной платформе (размер ptrdiff_t и размер int 32 бита) и на 64-битной модели IPL64 (где размеры ptrdiff_t и int 64 бита), но даст неверный результат на 64-битной платформе модели LP64 или LLP64, где размер ptrdiff_t 64 бита, а размер int 32 бита. [16]

Утилита printf

Утилита имеет следующий формат вызова: printf format [argument …] , где

  • format — строка формата, по синтаксису похожая на строку формата функции printf.
  • argument — список аргументов (0 или более), записанных в строковой форме.

Примеры реализации

Ссылки

  1. Краткое описание языка BCPL
  2. Руководство по языку Би
  3. Описание функции sprintf в документации Perl
  4. Описание форматирующего оператора для строковых типов в Питоне
  5. Описание функции printf в составе PHP
  6. Описание функции java.io.PrintStream.printf() в Java 1.5
  7. Описание функции printf в документации Ruby
  8. Описание функции format в документации TCL
  9. Описание шаблона строки для printf в документации GNU Octave
  10. Описание printf в документации к Maple<<подст:АИ>>
  11. R. Fourer, D.M. Gay, and B.W. Kernighan. AMPL: A Modeling Language for Mathematical Programming, 2nd Ed.. Pacific Grove, CA: Brooks/Cole--Thomson Learning, 2003.
  12. GNU Emacs Lisp Reference Manual, Formatting Strings
  13. Описание модуля Printf в документации OCaml
  14. §7.11.1.1 ISO/IEC 9899:TC2, LC_NUMERIC определяет, в частности, форму представления разделителя дробной и целой части.
  15. Описание уязвимостей printf, Robert C. Seacord: Secure Coding in C and C++. Addison Wesley, September, 2005. ISBN 0-321-33572-4
  16. Описание проблем переноса приложений с 32 на 64 битную архитектуру. [1]

Источники

  • printf, fprintf, snprintf, vfprintf, vprintf, vsnprintf, vsprintf в стандарте ISO/IEC 9899:TC2 (ISO C) [4]
  • printf, fprintf, sprintf, snprintf в стандарте Single Unix [5]
  • vprintf, vfprintf, vsprintf, vsnprintf в стандарте [6]
  • wprintf, swprintf, wprintf в стандарте [7]
  • vfwprintf, vswprintf, vwprintf в стандарте [8]
  • wsprintf в MSDN[9]
  • wvnsprintf в MSDN [10]
  • wnsprintf в MSDN [11]
  • wvsprintf в MSDN [12]
  • wnsprintf в MSDN [13]
  • asprintf, vasprintf в man-pages в Linux [14], в документации к libc [15]
  • Описание синтаксиса строки форматирования в руководстве libc [16].
  • Описание строки форматирования в документации к Microsoft Visual Studio 2005 [17]
  • Описание register_printf_function[18], [19]

См также

Wikimedia Foundation . 2010 .

Смотреть что такое "Vprintf" в других словарях:

Printf — printf обобщённое название семейства функций или методов стандартных или широкоизвестных коммерческих библиотек, или встроенных операторов некоторых языков программирования, используемых для форматного вывода вывода в различные потоки … Википедия

Snprintf — printf обобщённое название семейства функций или методов стандартных или широкоизвестных коммерческих библиотек, или встроенных операторов некоторых языков программирования, используемых для форматного вывода вывода в различные потоки значений… … Википедия

Sprintf — printf обобщённое название семейства функций или методов стандартных или широкоизвестных коммерческих библиотек, или встроенных операторов некоторых языков программирования, используемых для форматного вывода вывода в различные потоки значений… … Википедия

Swprintf — printf обобщённое название семейства функций или методов стандартных или широкоизвестных коммерческих библиотек, или встроенных операторов некоторых языков программирования, используемых для форматного вывода вывода в различные потоки значений… … Википедия

Vasprintf — printf обобщённое название семейства функций или методов стандартных или широкоизвестных коммерческих библиотек, или встроенных операторов некоторых языков программирования, используемых для форматного вывода вывода в различные потоки значений… … Википедия

Vfprintf — printf обобщённое название семейства функций или методов стандартных или широкоизвестных коммерческих библиотек, или встроенных операторов некоторых языков программирования, используемых для форматного вывода вывода в различные потоки значений… … Википедия

Vsprintf — printf обобщённое название семейства функций или методов стандартных или широкоизвестных коммерческих библиотек, или встроенных операторов некоторых языков программирования, используемых для форматного вывода вывода в различные потоки значений… … Википедия

Vsnprintf — printf обобщённое название семейства функций или методов стандартных или широкоизвестных коммерческих библиотек, или встроенных операторов некоторых языков программирования, используемых для форматного вывода вывода в различные потоки значений… … Википедия

Wprintf — printf обобщённое название семейства функций или методов стандартных или широкоизвестных коммерческих библиотек, или встроенных операторов некоторых языков программирования, используемых для форматного вывода вывода в различные потоки значений… … Википедия

Wsprintf — printf обобщённое название семейства функций или методов стандартных или широкоизвестных коммерческих библиотек, или встроенных операторов некоторых языков программирования, используемых для форматного вывода вывода в различные потоки значений… … Википедия

sprintf

(PHP 4, PHP 5, PHP 7)

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

Описание

Возвращает строку, созданную с использованием строки формата 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 игнорирует значения ширины и дополнения

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

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

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

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

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

Примеры

Пример #1 Argument swapping

Строка формата поддерживает нумерацию и перемешивание аргументов.

= 5 ;
$location = 'tree' ;

$format = 'There are %d monkeys in the %s' ;
echo sprintf ( $format , $num , $location );
?>

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

Теперь представим, что строка форматирования задается в стороннем файле. Это обычная практика при необходимости поддержки нескольких языков. Представим, что строка была переписана таким образом:

Упс! У нас проблема - порядок спецификаторов пересал соответствовать порядку аргументов. Так как нам очень не хочется менять код каждый раз, когда меняется формат строки, то мы можем использовать нумерованные аргументы:

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

При использовании нумерованных аргументов, спецификатор позиции n$ должен стоять сразу же за символом процента (%), до любого другого спецификатора, как показано ниже.

Пример #2 Использование символа заполнения

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

Пример #3 Спецификатор позиции в комбинации с другими спецификаторами

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

Пример #4 sprintf() : целое с лидирующими нулями

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

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

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

echo sprintf ( "%.3e" , $number );
?>

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

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

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

User Contributed Notes 40 notes

1. A plus sign ('+') means put a '+' before positive numbers while a minus sign ('-') means left justify. The documentation incorrectly states that they are interchangeable. They produce unique results that can be combined:

echo sprintf ( "|%+4d|%+4d|\n" , 1 , - 1 );
echo sprintf ( "|%-4d|%-4d|\n" , 1 , - 1 );
echo sprintf ( "|%+-4d|%+-4d|\n" , 1 , - 1 );
?>

outputs:

2. Padding with a '0' is different than padding with other characters. Zeros will only be added at the front of a number, after any sign. Other characters will be added before the sign, or after the number:

echo sprintf ( "|%04d|\n" , - 2 );
echo sprintf ( "|%':4d|\n" , - 2 );
echo sprintf ( "|%-':4d|\n" , - 2 );

// Specifying both "-" and "0" creates a conflict with unexpected results:
echo sprintf ( "|%-04d|\n" , - 2 );

// Padding with other digits behaves like other non-zero characters:
echo sprintf ( "|%-'14d|\n" , - 2 );
echo sprintf ( "|%-'04d|\n" , - 2 );
?>

outputs:

With printf() and sprintf() functions, escape character is not backslash '\' but rather '%'.

Ie. to print '%' character you need to escape it with itself:
( '%%%s%%' , 'koko' ); #output: '%koko%'
?>

There are already some comments on using sprintf to force leading leading zeros but the examples only include integers. I needed leading zeros on floating point numbers and was surprised that it didn't work as expected.

Example:
( '%02d' , 1 );
?>

This will result in 01. However, trying the same for a float with precision doesn't work:

This threw me a little off. To get the desired result, one needs to add the precision (2) and the length of the decimal seperator "." (1). So the correct pattern would be

Please see http://stackoverflow.com/a/28739819/413531 for a more detailed explanation.

Here is how to print a floating point number with 16 significant digits regardless of magnitude:

= sprintf ( sprintf ( '%%.%dF' , max ( 15 - floor ( log10 ( $value )), 0 )), $value );
?>

This works more reliably than doing something like sprintf('%.15F', $value) as the latter may cut off significant digits for very small numbers, or prints bogus digits (meaning extra digits beyond what can reliably be represented in a floating point number) for very large numbers.

I had a nightmare trying to find the two's complement of a 32 bit number.

Quote: . find out the 2's complement of any number, which is -(pow(2, n) - N) where n is the number of bits and N is the number for which to find out its 2's complement.

This worked magic for me. previously I was trying to use

sprintf ("%b",$32BitDecimal);
But it always returned 10000000000000000000000 when the $32BitDecimal value got above 2,000,000,000.

This -(pow(2, n) - N)
Worked remarkably well and was very accurate.

Hope this helps someone fighting with two's complement in PHP.

Note that when using the argument swapping, you MUST number every argument, otherwise sprintf gets confused. This only happens if you use number arguments first, then switch to a non-numbered, and then back to a numbered one.

= sprintf ( "select * from %1\$s left join %2\$s on( %1\$s. and %2\$s.tagname is not null" , "table1" , "table2" , "bob" );
// Wont work:
// Sprintf will complain about not enough arguments.
$sql = sprintf ( "select * from %1\$s left join %2\$s on( %1\$s. and %2\$s.tagname is not null" , "table1" , "table2" , "bob" );
// Will work: note the %3\$s
?>

Using argument swapping in sprintf() with gettext: Let's say you've written the following script:

= sprintf ( gettext ( "The %2\$s contains %1\$d monkeys" ), 2 , "cage" );
?>

Now you run xgettext in order to generate a .po file. The .po file will then look like this:

#: file.php:9
#, ycp-format
msgid "The %2\\$s contains %1\\$d monkeys"
msgstr ""

Notice how an extra backslash has been added by xgettext.

Once you've translated the string, you must remove all backslashes from the ID string as well as the translation, so the po file will look like this:

#: file.php:9
#, ycp-format
msgid "The %2$s contains %1$d monkeys"
msgstr "Der er %1$d aber i %2$s"

Now run msgfmt to generate the .mo file, restart Apache to remove the gettext cache if necessary, and you're off.

If you use the default padding specifier (a space) and then print it to HTML, you will notice that HTML does not display the multiple spaces correctly. This is because any sequence of white-space is treated as a single space.

To overcome this, I wrote a simple function that replaces all the spaces in the string returned by sprintf() with the character entity reference " " to achieve non-breaking space in strings returned by sprintf()

//Here is the function:
function sprintf_nbsp () <
$args = func_get_args ();
return str_replace ( ' ' , ' ' , vsprintf ( array_shift ( $args ), array_values ( $args )));
>

//Usage (exactly like sprintf):
$format = 'The %d monkeys are attacking the [%10s]!' ;
$str = sprintf_nbsp ( $format , 15 , 'zoo' );
echo $str ;
?>

The above example will output:
The 15 monkeys are attacking the [ zoo]!

//The variation that prints the string instead of returning it:
function printf_nbsp () <
$args = func_get_args ();
echo str_replace ( ' ' , ' ' , vsprintf ( array_shift ( $args ), array_values ( $args )));
>
?>

A more complete and working version of mb_sprintf and mb_vsprintf. It should work with any "ASCII preserving" encoding such as UTF-8 and all the ISO-8859 charsets. It handles sign, padding, alignment, width and precision. Argument swapping is not handled.

if (! function_exists ( 'mb_sprintf' )) <
function mb_sprintf ( $format ) <
$argv = func_get_args () ;
array_shift ( $argv ) ;
return mb_vsprintf ( $format , $argv ) ;
>
>
if (! function_exists ( 'mb_vsprintf' )) <
/**
* Works with all encodings in format and arguments.
* Supported: Sign, padding, alignment, width and precision.
* Not supported: Argument swapping.
*/
function mb_vsprintf ( $format , $argv , $encoding = null ) <
if ( is_null ( $encoding ))
$encoding = mb_internal_encoding ();

// Use UTF-8 in the format so we can use the u flag in preg_split
$format = mb_convert_encoding ( $format , 'UTF-8' , $encoding );

$newformat = "" ; // build a new format in UTF-8
$newargv = array(); // unhandled args in unchanged encoding

// Split the format in two parts: $pre and $post by the first %-directive
// We get also the matched groups
list ( $pre , $sign , $filler , $align , $size , $precision , $type , $post ) =
preg_split ( "!\%(\+?)('.|[0 ]|)(-?)([1-9][0-9]*|)(\.[1-9][0-9]*|)([%a-zA-Z])!u" ,
$format , 2 , PREG_SPLIT_DELIM_CAPTURE ) ;

$newformat .= mb_convert_encoding ( $pre , $encoding , 'UTF-8' );

if ( $type == '' ) <
// didn't match. do nothing. this is the last iteration.
>
elseif ( $type == '%' ) <
// an escaped %
$newformat .= '%%' ;
>
elseif ( $type == 's' ) <
$arg = array_shift ( $argv );
$arg = mb_convert_encoding ( $arg , 'UTF-8' , $encoding );
$padding_pre = '' ;
$padding_post = '' ;

// define padding
if ( $size > 0 ) <
$arglen = mb_strlen ( $arg , $encoding );
if ( $arglen $size ) <
if( $filler === '' )
$filler = ' ' ;
if ( $align == '-' )
$padding_post = str_repeat ( $filler , $size - $arglen );
else
$padding_pre = str_repeat ( $filler , $size - $arglen );
>
>

// escape % and pass it forward
$newformat .= $padding_pre . str_replace ( '%' , '%%' , $arg ) . $padding_post ;
>
else <
// another type, pass forward
$newformat .= "% $sign$filler$align$size$precision$type " ;
$newargv [] = array_shift ( $argv );
>
$format = strval ( $post );
>
// Convert new format back from UTF-8 to the original encoding
$newformat = mb_convert_encoding ( $newformat , $encoding , 'UTF-8' );
return vsprintf ( $newformat , $newargv );
>
>
?>

I created this function a while back to save on having to combine mysql_real_escape_string onto all the params passed into a sprintf. it works literally the same as the sprintf other than that it doesn't require you to escape your inputs. Hope its of some use to people

function mressf ()
<
$args = func_get_args ();
if ( count ( $args ) 2 )
return false ;
$query = array_shift ( $args );
$args = array_map ( 'mysql_real_escape_string' , $args );
array_unshift ( $args , $query );
$query = call_user_func_array ( 'sprintf' , $args );
return $query ;
>
?>

Regards
Jay
Jaygilford.com

Using sprintf to force leading leading zeros

foreach (range(1, 10) as $v) tag_".sprintf("%02d",$v);>

Encoding and decoding IP adress to format: 1A2B3C4D (mysql column: char(8) )

function encode_ip ( $dotquad_ip )
<
$ip_sep = explode ( '.' , $dotquad_ip );
return sprintf ( '%02x%02x%02x%02x' , $ip_sep [ 0 ], $ip_sep [ 1 ], $ip_sep [ 2 ], $ip_sep [ 3 ]);
>

function decode_ip ( $int_ip )
<
$hexipbang = explode ( '.' , chunk_split ( $int_ip , 2 , '.' ));
return hexdec ( $hexipbang [ 0 ]). '.' . hexdec ( $hexipbang [ 1 ]) . '.' . hexdec ( $hexipbang [ 2 ]) . '.' . hexdec ( $hexipbang [ 3 ]);
>
?>

If you want to convert a decimal (integer) number into constant length binary number in lets say 9 bits, use this:

$binary = sprintf('%08b', $number );

for example:
= sprintf ( '%08b' , 511 );
echo $bin . "\n" ;
?>

would output 111111111
And 2 would output 00000010

I know the leading zeros are useful to me, perhaps they are to someone else too.

$format = 'There are %1$d monkeys in the %s and %s ';
printf($format, 100, 'Chennai', 'Bangalore');

Expecting to output
"There are 100 monkeys in the Chennai and bangalore"

But, this will output
"There are 100 monkeys in the 100 and Chennai"

Because, the second and Third specifiers takes 1rst and 2nd arguments. Because it is not assigned with any arguments.

If you use argument numbering, then format specifications with the same number get the same argument; this can save repeating the argument in the function call.

printf ( $pattern , "badgers" );
?>

And continuing on the same theme of a key-based sprintf.

I'm roughly (I can see a couple cases where it comes out wierd) copying the syntax of Python's string formatting with a dictionary. The improvement over the several past attempts is that this one still respects all of the formating options, as you can see in my example.

And the error handling is really crappy (just an echo). I just threw this together so do with it what you will. =]

function sprintf_array ( $string , $array )
<
$keys = array_keys ( $array );
$keysmap = array_flip ( $keys );
$values = array_values ( $array );

while ( preg_match ( '/%\(([a-zA-Z0-9_ -]+)\)/' , $string , $m ))
<
if (!isset( $keysmap [ $m [ 1 ]]))
<
echo "No key $m [ 1 ] \n" ;
return false ;
>

$string = str_replace ( $m [ 0 ], '%' . ( $keysmap [ $m [ 1 ]] + 1 ) . '$' , $string );
>

array_unshift ( $values , $string );
var_dump ( $values );
return call_user_func_array ( 'sprintf' , $values );
>

echo sprintf_array ( '4 digit padded number: %(num)04d ' , array( 'num' => 42 ));

Here's a clean, working version of functions to allow using named arguments instead of numeric ones. ex: instead of sprintf('%1$s', 'Joe');, we can use sprintf('%name$s', array('name' => 'Joe'));. I've provided 2 different versions: the first uses the php-like syntax (ex: %name$s), while the second uses the python syntax (ex: %(name)s).

/**
* version of sprintf for cases where named arguments are desired (php syntax)
*
* with sprintf: sprintf('second: %2$s ; first: %1$s', '1st', '2nd');
*
* with sprintfn: sprintfn('second: %second$s ; first: %first$s', array(
* 'first' => '1st',
* 'second'=> '2nd'
* ));
*
* @param string $format sprintf format string, with any number of named arguments
* @param array $args array of [ 'arg_name' => 'arg value', . ] replacements to be made
* @return string|false result of sprintf call, or bool false on error
*/
function sprintfn ( $format , array $args = array()) <
// map of argument names to their corresponding sprintf numeric argument value
$arg_nums = array_slice ( array_flip ( array_keys (array( 0 => 0 ) + $args )), 1 );

// find the next named argument. each search starts at the end of the previous replacement.
for ( $pos = 0 ; preg_match ( '/(? , $format , $match , PREG_OFFSET_CAPTURE , $pos );) <
$arg_pos = $match [ 0 ][ 1 ];
$arg_len = strlen ( $match [ 0 ][ 0 ]);
$arg_key = $match [ 1 ][ 0 ];

// programmer did not supply a value for the named argument found in the format string
if (! array_key_exists ( $arg_key , $arg_nums )) <
user_error ( "sprintfn(): Missing argument ' $ < arg_key >'" , E_USER_WARNING );
return false ;
>

// replace the named argument with the corresponding numeric one
$format = substr_replace ( $format , $replace = $arg_nums [ $arg_key ], $arg_pos , $arg_len );
$pos = $arg_pos + strlen ( $replace ); // skip to end of replacement for next iteration
>

return vsprintf ( $format , array_values ( $args ));
>

/**
* version of sprintf for cases where named arguments are desired (python syntax)
*
* with sprintf: sprintf('second: %2$s ; first: %1$s', '1st', '2nd');
*
* with sprintfn: sprintfn('second: %(second)s ; first: %(first)s', array(
* 'first' => '1st',
* 'second'=> '2nd'
* ));
*
* @param string $format sprintf format string, with any number of named arguments
* @param array $args array of [ 'arg_name' => 'arg value', . ] replacements to be made
* @return string|false result of sprintf call, or bool false on error
*/
function sprintfn ( $format , array $args = array()) <
// map of argument names to their corresponding sprintf numeric argument value
$arg_nums = array_slice ( array_flip ( array_keys (array( 0 => 0 ) + $args )), 1 );

// find the next named argument. each search starts at the end of the previous replacement.
for ( $pos = 0 ; preg_match ( '/(? , $format , $match , PREG_OFFSET_CAPTURE , $pos );) <
$arg_pos = $match [ 0 ][ 1 ];
$arg_len = strlen ( $match [ 0 ][ 0 ]);
$arg_key = $match [ 1 ][ 0 ];

// programmer did not supply a value for the named argument found in the format string
if (! array_key_exists ( $arg_key , $arg_nums )) <
user_error ( "sprintfn(): Missing argument ' $ < arg_key >'" , E_USER_WARNING );
return false ;
>

// replace the named argument with the corresponding numeric one
$format = substr_replace ( $format , $replace = $arg_nums [ $arg_key ] . '$' , $arg_pos , $arg_len );
$pos = $arg_pos + strlen ( $replace ); // skip to end of replacement for next iteration
>

return vsprintf ( $format , array_values ( $args ));
>

Форматированный вывод и fprintf

Я написал эту небольшую программу C:

Затем я проанализировал data.txt с помощью xxd -b . Я ожидал, что увижу 32-битное представление 578 вместо этого, я увидел ASCII-представление 578:

Почему? Как сохранить 32-битное представление 578 (01000010 00000010 00000000 00000000), если предположить, что он немного endian?

fprintf предназначен для форматированного вывода, откуда находится конечный f .

Это значение "Отформатировано". Вы использовали квалификатор %d , который означает "отформатируйте данное значение как числовое представление ASCII в наборе символов выполнения, предполагая, что это целое число со знаком".

Если вы хотите записать двоичные данные в файл - не, используйте форматированный вывод. Используйте fwrite вместо того, чтобы писать сырые двоичные данные.

Vprintf, vfprintf, vsprintf форматный вывод

Функция printf переводит внутренние значения в текст.

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

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

Форматная строка содержит два вида объектов: обычные символы, которые напрямую копируются в выходной поток, и спецификации преобразования, каждая из которых вызывает преобразование и печать очередного аргумента printf . Любая спецификация преобразования начинается знаком % и заканчивается символом-спецификатором. Между % и символом-спецификатором могут быть расположены (в указанном ниже порядке) следующие элементы:

  • Знак минус, предписывающий выравнивать преобразованный аргумент по левому краю поля.
  • Число, специфицирующее минимальную ширину поля. Преобразованный аргумент будет занимать поле по крайней мере указанной ширины. при необходимости лишние позиции слева (или справа при левостороннем расположении) будут заполнены пробелами.
  • Точка, отделяющая ширину поля от величины, устанавливающей точность.
  • Число (точность), задающее максимальное количество печатаемых символов в строке, или количество цифр после десятичной точки (для чисел с плавающей запятой), или минимальное количество цифр (для целых чисел).
  • Буква h , если печатаемое целое должно рассматриваться как short , или l (строчная латинская буква L), если целое должно рассматриваться как long .

Символы-спецификаторы перечислены в таблице 7.1. Если за % не помещен символ-спецификатор, поведение функции printf будет не определено.

Таблица 7.1. Основные преобразования printf

Символ Тип аргумента; вид печати
d , i int ; десятичное целое
o int ; беззнаковое восьмеричное (octal) целое (без нуля слева)
x , X unsigned int ; беззнаковое шестнадцатиричное целое (без 0x или 0X слева), для шестнадцатиричных цифр от 10 до 15 используются символы a , b , c , d , e , f или A , B , C , D , E , F
u int ; беззнаковое десятичное целое
c int ; одиночный символ
s char * ; печатает символы, пока не встретится символ \0 , или количество символов, заданное точностью
f double ; [-] m.dddddd, где количество цифр d задается точностью (по умолчанию равно 6)
e , E double ; [-] m.dddddd e + xx или [-] m.dddddd E + xx, где количество цифр d задается точностью (по умолчанию равно 6)
g , G double ; использует %e или %E , если порядок меньше, чем -4, или больше или равен точности; в противном случае использует %f. Завершающие нули и завершающая десятичная точка не печатаются
p void * ; указатель (представление зависит от реализации)
% Аргумент не преобразуется; печатается знак %

Ширину и точность можно задавать с помощью знака * ; значение ширины (или точности) в этом случае берется из следующего аргумента, который должен быть типа int . Например, чтобы напечатать не более max символов из строки s , годится следующая запись:

Большая часть форматных преобразований была продемонстрирована в предыдущих главах. Исключение составляет задание точности для строк. Далее приводится перечень спецификаций и показывается их влияние на печать строки «hello, world», состоящей из 12 символов. Поле специально обрамлено двоеточиями, чтобы была видна его протяженность.

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

Функция sprintf выполняет те же преобразования, что и printf , но вывод запоминается в строке

Эта функция форматирует аргументы arg 1 , arg 2 и т.д. в соответствии с информацией, заданной аргументом format , как мы описывали ранее, но результат помещает не в стандартный вывод, а в string . Заметим, что строка string должна быть достаточно большой, чтобы в ней поместился результат.

Vprintf, vfprintf, vsprintf форматный вывод

Функции производят форматированный вывод в символьную строку (функция библиотеки С и С++).

Синтаксис

Параметры

Указатель на строку, в которую осуществляется вывод.

Максимальное число символов, которое сохраняется в версии Unicode этой функции.

Переменное число параметров (дополнительные параметры).

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

В случае ошибки возвращается EOF (WEOF)

Функция возвращает число записанных символов или – (минус)1, если произошла ошибка. Если string или format - пустой указатель, вызывается обработчик недопустимых параметров, как описано в статье Проверка достоверности параметров. Если разрешено исполнение кода, чтобы продолжить, эти функции возвращают значение -(минус)1 и устанавливают errno в EINVAL.

Функция sprintf возвращает число байтов, сохраненное в буфере, не считая символ завершающего нуля. Функция swprintf возвращает число "широких " символов, сохраненных в буфере, не считая "широкого " завершающегося нулевого символа.

Замечания

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

Функция sprintf форматирует и записывает ряд символов и значений в массиве вывода данных, на который ссылается параметр string. Если параметры следуют за строкой format, то форматирующая (format) строка должна содержать спецификации, которые определяют формат вывода для параметров. Функции sprintf и printf ведут себя тождественно за исключением того, что printf печатает выводимые данные в stdout, а не в массив выводимых данных (строку).

Функция swprintf - широкосимвольная версия sprintf (для Unicode); format - широкосимвольная строка. Функции swprintf и sprintf во всем остальном ведут себя тождественно.

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

Спецификации формата всегда начинаются со знака процента (%) и читается слева направо. Когда функция sprintf встречается с первой спецификацией формата (если она есть), то преобразует значение первого параметра после format и выводит его соответственно. Вторая спецификация формата заставляет второй параметр быть преобразованным и выведенным и так далее. Если имеется больше параметров, чем есть их спецификаций, дополнительные параметры игнорируются. Результаты не определяются, если недостаточно параметров для всех спецификаций формата.

Замечание по обеспечению безопасности! Убедитесь в том, что формат не определяемая пользователем строка.

Демонстрационный пример

Вывод данных

Смотри также

Процедуры поддержки плавающей запятой | Процедуры потоков ввода-вывода (I/O) | Локальные процедуры | Функции fopen | fprintf | scanf | sprintf | vprintf | Процедуры времени исполнения программы и эквиваленты .NET Framework

Требования

Процедуры

Требуется заголовочный файл

Совместимость

sprintf ANSI, Win 98, Win Me, Win NT, Win 2000, Win XP swprintf или ANSI, Win 98, Win Me, Win NT, Win 2000, Win XP

Дополнительную информацию о совместимости см. в статье Совместимость в главе Введение.

Библиотеки

Все версии библиотек времени исполнения программы C.

Функции sprintf_s, _sprintf_s_l, swprintf_s, _swprintf_s_l, swprintf и _swprintf_l

Записывает форматированные данные в строку. Доступны более безопасные версии некоторых из этих функций; см. sprintf_s, _sprintf_s_l, swprintf_s, _swprintf_s_l. У swprintf и _swprintf_l нет более безопасной версии, потому что они получают параметр подсчета.

Синтаксис

Параметры

Место хранения для выводимых данных.

Максимальное число символов, которое хранится в версии Unicode этой функции.

Параметр строки управления форматом. Это дополнительные (необязательные) параметры.

Используемый язык страны (местности).

Для получения дополнительной информации, см. статью Спецификации формата.

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

Замечания

Замечание по безопасности: При использовании функции sprintf, нет какого-либо способа ограничить число записываемых символов, что означает, что код, используя sprintf, восприимчив к переполнению буфера. Примите во внимание то, что лучше использовать связанные функции _snprintf, которая определяет максимальное число символов, которые будут записаны в буфер или _scprintf, которая определяет какой величины буфер требуется. Кроме того, обеспечьте, чтобы формат являлся не определяемой пользователем строкой.

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

В Visual C++ 2005, функция swprintf приведена в соответствие со Стандартом C Международной Организации по Стандартизации (ISO), который требует второго параметра count, типа size_t. Чтобы заставить действовать старое нестандартное поведение функции, определите флажок _CRT_NON_CONFORMING_SWPRINTFS . В будущей версии может быть удалено старое поведение функции, таким образом код должен меняться для использования нового соответствующего стандарту поведения.

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

Илон Маск рекомендует:  Безопасное программирование
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL