Форматный вывод есть специальная разновидность буферизованного вывода, где запись информации в поток сопровождается форматным преобразованием данных базовых типов. Характер преобразования обеспечивает требуемый символьный формат вывода данных в поток. В системе программирования C форматный вывод реализуют функции fprintf, printf и sprintf.
Универсальную возможность форматирования вывода данных базовых типов для их записи в файловый или стандартный поток предоставляет функция fprintf. Спецификация формата ее вызова имеет вид:
int fprintf(FILE* stream, const char* format[, arg]...);
Функция fprintf выполняет преобразование набора своих необязательных аргументов arg согласно спецификации, заданной строкой символов format, для вывода форматированных данных в поток, который обозначает указатель stream. Код возврата определяет число символов, которые были записаны в поток вывода в результате форматных преобразований всех аргументов. При аварийном завершении функция fprintf возвращает отрицательный код.
Функция fprintf предусматривает возможность обработки произвольного числа своих необязательных аргументов arg, через которые ей могут быть переданы значения переменных базовых типов. При выводе каждый аргумент преобразуется в символьную форму своего представления. Формат результата определяют параметры символьной строки format, специфицированные в ней для каждого аргумента.
Символьная строка format содержит два типа объектов: обычные символы, которые передаются в поток без преобразований, и спецификаторы формата вывода аргументов. Каждый спецификатор должен начинаться с символа '%'. После него могут быть последовательно указаны параметры, которые задают флаг формы вывода, ширину поля вывода, точность и тип преобразования аргумента. В общем случае спецификатор формата имеет следующий вид:
%[flag][width][.prec]type
Необязательные параметры флага flag спецификатора формата устанавливают форму поля вывода. Они могут принимать значения: '-', '0', '+' или '#'. Флаг '-' задает выравнивание поля вывода аргумента по левой границе. По умолчанию принято выравнивание по правой границе. Флаг '0' обеспечивает дополнение поля вывода лидирующими нулями для числовых типов данных. По умолчанию поле вывода должно быть дополнено символами пробел. Флаг '+' гарантирует обязательную печать знака (+ или -) для числовых данных. По умолчанию знак числа выводится только для отрицательных данных. Флаг '#' означает преобразование числовых данных к альтернативной форме вывода. В частности, представление чисел в системах счисления по основанию 16 и 8 будет дополнено префиксами 0x (или 0X) и 0, cоответственно.
Необязательный параметр width спецификатора формата задает минимальное число выводимых символов аргумента. Если значение аргумента короче, чем заданная ширина поля вывода, то оно будет дополнено символами '0' или пробел по спецификации параметра flag.
Необязательный параметр prec спецификатора формата указывает точность преобразований, которую задает последовательность десятичных цифр после знака точки. Для целочисленных данных точность означает минимальное число цифр, которое должно быть выведено. Для вещественных данных этот параметр задает максимальное число значащих цифр мантиссы. При выводе символьных строк точность преобразований ограничивает число выводимых символов.
Параметр type спецификатора формата задает буквенное обозначение типа преобразований значения аргумента при выводе в поток. Может быть задано преобразование к формату целого числа со знаком или без знака в системе счисления по основанию 8, 10, 16 и вещественного числа с фиксированной точкой или в экспоненциальной форме. Кроме того, аргумент может быть интерпретирован как отдельный символ или строка символов.
Чтобы декларировать преобразование значения аргумента к различным формам представления целых чисел, в параметре type следует указать буквы: d, i, u, o, x или X. В частности, литеры d и i представляют аргумент в формате целого десятичного числа со знаком. Буквы u, o, x или X применяются для преобразования аргумента к формату целого числа без знака в системах счисления по основанию 10, 8 и 16, соответственно. Выбор литеры x или X влияет на регистр изображения шести старших цифр в системе счисления по основанию 16.
Форматирование целочисленных данных иллюстрирует следующий исходный код прикладной процедуры radix, которая отображает через поток стандартной диагностики символическое представление заданного значения аргумента в различных позиционных системах счисления.
/* Форматные преобразования системы счисления */
void radix(unsigned value) {
static char* format[] = { /* Формат системы счисления */
                           "oct: %#o  ",  /* основание 8  */
                           "dec: %u  ",   /* основание 10 */
                           "hex: %#x\n"   /* основание 16 */
                         };
int i = 0;   /* Индекс форматной строки */
/* Цикл форматных преобразований */
while(i < 3)
   fprintf(stderr, format[i++], value);
} /* radix */
Итерации цикла вызова функции fprintf процедуры radix последовательно отображают значение параметра value в системах счисления по основанию 8, 10 и 16. Представление числа в системах счисления по основаниям 8 и 16 сопровождается лидирующим префиксом, соответственно, 0 и 0x, вывод которого обеспечивает спецификация флага #. Например, вызов процедуры radix с параметром 127 приведет к отображению следующей строки:
oct: 0177  dec: 127  hex: 0x7f
Для преобразования значения аргумента к различным формам представления вещественных чисел в параметре type используются буквы f, e или E и g или G. Буква f обеспечит представление аргумента в форме вещественного числа с фиксированной точкой. Число цифр после десятичной точки равно значению параметра точности. Если точность не указана, то после точки выводится 6 цифр. Если задана нулевая точность, то десятичная точка и дробная часть не выводятся. Буквы e и E применяются для представления вещественного аргумента в экспоненциальной форме, где перед десятичной точкой только одна цифра, а число цифр после точки определяет параметр точности аналогично формату числа с фиксированной точкой. Вывод числа в экспоненциальной форме завершает значение порядка после символа e или E. Поле порядка всегда содержит не менее двух цифр. При необходимости оно дополняется лидирующим нулем. Если форма вывода вещественного числа безразлична, но необходимо минимизировать длину поля его представления, параметр type должен быть специфицирован буквой g или G. При этом будет автоматически выбран формат, который гарантирует нужную точность представления минимальным числом значащих цифр. Регистр параметра определяет регистр символа порядка числа в экспоненциальной форме его представления.
Следующие примеры демонстрируют вывод действительного числа 1234.56789 при различных форматах вещественных преобразований с учетом параметров ширины поля вывода и точности представления результата, где симол “тильда” условно обозначает лидирующий пробел:
 Формат: "%f"           Вывод: 1234.567890
 Формат: "%.1f"         Вывод: 1234.6
 Формат: "%E"           Вывод: 1.234568E+03
 Формат: "%.3e"         Вывод: 1.235e+03
 Формат: "%g"           Вывод: 1234.57
 Формат: "%12f"         Вывод: ~1234.567890
 Формат: "%3f"          Вывод: 1234.567890
 Формат: "%14E"         Вывод: ~~1.234568E+03
 Формат: "%3e"          Вывод: 1.234568e+03
 Формат: "%8.1f"        Вывод: ~~1234.6
 Формат: "%-8.1f"       Вывод: 1234.6
 Формат: "%8.1e"        Вывод: ~1.2e+03
 Формат: "%-8.1E"       Вывод: 1.2E+03
Перечисленные значения параметра типа преобразований могут быть указаны с модифицирующим префиксом h, l или L. Модификаторы h и l декларируют, что следующий за ними символ целочисленного преобразования формы вывода применяется к аргументам типа short или unsigned short и long или unsigned long. Модификатор L указывает, что следующий после него символ преобразования к формату вещественного числа используется для аргумента типа long double. Например, спецификация "%ld" обеспечивает форматный вывод данных типа long.
Для форматирования вывода символьной информации значение параметра type должно быть задано буквами s или с. Если указана буква s, то аргумент будет интерпретирован как строка символов. Количество символов строки, которые будут записаны в поток, ограничено значением параметра точности преобразований. Если точность не указана или больше длины строки, то в поток будут выведены все символы до кода '\0'. Например, спецификация "%s" или "%10s" гарантирует вывод всех символов строки "Linux". Однако, если задан формат "%.2s" или "%5.2s", информативный вывод той же строки будет обрезан до двух символов Li. Во втором случае, вывод также дополняется префиксом из трех лидирующих пробелов, потому что указана ширина поля из пяти символов.
Если значение параметра type в спецификации формата пребразований задано буквой c, то значение аргумента функции fprintf рассматривается как код одиночного символа, который нужно записать в поток. Значение аргумента при выводе в поток будет преобразовано к типу unsigned char. Форматные преобразования символьной информации поясняет исходный код прикладной процедуры alphabit, которая отображает латинский алфавит в поток стандартного вывода:
/* Латинский алфавит */
void alphabit() {
char c = 'a';   /* код буквы алфавита */
int i;          /* номер буквы алфавита */
for(i = 0; i < 26; i++)
  fprintf(stdout, "%2c", c++);
fprintf(stdout, "%c", '\n');
} /* alphabit */
В процедуре alphabit предполагается, что коды латинских букв образуют монотонно возрастающую последовательность, где все буквы упорядочены по алфавиту. Чтобы разделить соседние буквы в потоке стандартного вывода символом пробел, в форматной строке указана ширина поля. Вывод символа с кодом '\n' обеспечивает перевод строки за последней буквой алфавита.
Кроме рассмотренных выше спецификаций форматных преобразований потока вывода предусмотрена возможность измерения объема записанных данных. Чтобы выполнить такое измерение, параметр типа преобразований должен быть специфицирован буквой n. Результат измерений должен передаваться через указатель на целое число. По этому указателю будет записано число байтов, которые выведены в поток по предыдущим спецификациям форматной строки. Измерение не приводит к записи информации в поток вывода, но может быть использовано для контроля форматных преобразований.
Кроме функции fprintf форматирование вывода обеспечивают функции printf и sprintf, которые идентичны функции fprintf по спецификации форматных преобразований и необязательных аргументов, но отличаются адресацией вывода данных. Код возврата этих функций также аналогичен коду возврата функции fprintf.
Функция printf реализует форматные преобразования данных для записи их результата в поток стандартного вывода. Это наиболее популярная функция системы программирования C. Обращение к ней эквивалентно вызову функции fprintf, когда указатель потока stream специфицирован значением stdout. Так как поток вывода функции printf определен однозначно, то при вызове нет необходимости передавать ей указатель потока.
Когда результат форматных преобразований данных нужно получить в формате строки символов вместо записи в файловый поток или в поток стандартного вывода, применяется функция sprintf. Вместо указателя потока (stream) ей передается адрес символьного массива, где нужно сохранить результаты форматных преобразований. Массив полученных символов дополняет нулевой код '\0', чтобы образовать символьную строку. Ее содержание может быть записано в поток вывода с помощью соответствующих функций стандартного буферизованного вывода.
Функция sprintf может быть полезна для преобразования числовых данных в формат строки символов. Следующий исходный код прикладной функции itoa поясняет принцип этого преобразования для целочисленных данных:
/* Преобразование целого числа в строку символов */
char* itoa(int value) {
static char buf[16];       /* буфер преобразований */
sprintf(buf, "%d", value); /* преобразование числа в строку */
return(buf);               /* возврат адреса строки */
} /* itoa */
Функция itoa преобразует значение своего целочисленного аргумента value в формат строки символов, для хранения которой предназначен статический массив, используя вызов функции sprintf с целочисленной спецификацией форматных преобразований. Адрес полученной строки передается через код возврата. Использование статического массива существенно для сохранения результата, потому что массив в классе auto будет разрушен при возврате из функции. Следует отметить, что функция itoa включена в стандартные библиотеки некоторых популярных реализаций системы программирования C, но отсутствует в стандарте языка C. Поэтому при разработке мобильных прикладных программ следует применять функцию sprintf, чтобы выполнять преобразование числовых данных в символический формат.