printf()

Содержание

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

int printf(const char *управляющая_строка, ...);

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

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

printf("Мне нравится язык %c %s", 'C', "и к тому же очень сильно!");

Будет выведено

Мне нравится язык C и к тому же очень сильно!

В этом примере первому спецификатору преобразования (%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 в экспоненциальном формате. В общем виде числа в таком формате выглядят следующим образом:

x.dddddE+/-yy

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

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

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

#include <stdio.h>

int main(void)
{
  double f;

  for(f=1.0; f<1.0e+10; f=f*10)
    printf("%g ", f);

  return 0;
}

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

1  10  100  1000  10000  100000  1e+06  1e+07  1e+08  1e+09

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

#include <stdio.h>

int main(void)
{
  unsigned num;

  for(num=0; num < 16; num++) {
    printf("%o ", num);
    printf("%x ", num);
    printf("%X\n", num);
  }

  return 0;
}

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

0 0 0
1 1 1
2 2 2
3 3 3
4 4 4
5 5 5
6 6 6
7 7 7
10 8 8
11 9 9
12 a A
13 b B
14 c C
15 d D
16 e E
17 f F

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


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

#include <stdio.h>

int sample;

int main(void)
{
  printf("%p", &sample);

  return 0;
}

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


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

#include <stdio.h>

int main(void)
{
  int count;

  printf("this%n is a test\n", &count);
  printf("%d", count);

  return 0;
}

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

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


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

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


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

#include <stdio.h>

int main(void)
{
  double item;

  item = 10.12304;

  printf("%f\n", item);
  printf("%10f\n", item);
  printf("%012f\n", item);

  return 0;
}

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

10.123040
 10.123040
00010.123040

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

#include <stdio.h>

int main(void)
{
  int i;

  /* вывод таблицы квадратов и кубов */
  for(i=1; i<20; i++)
    printf("%8d %8d %8d\n", i, i*i, i*i*i);

  return 0;
}

А вот пример полученного с ее помошью вывода:

 1       1       1
 2       4       8
 3       9      27
 4      16      64
 5      25     125
 6      36     216
 7      49     343
 8      64     512
 9      81     729
10     100    1000
11     121    1331
12     144    1728
13     169    2197
14     196    2744
15     225    3375
16     256    4096
17     289    4913
18     324    5832
19     361    6859

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


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

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

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

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

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

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

#include <stdio.h>

int main(void)
{
  printf("%.4f\n", 123.1234567);
  printf("%3.8d\n", 1000);
  printf("%10.15s\n", "Это простая проверка.");

  return 0;
}

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

123.1235
00001000
Это простая про

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


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

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

#include <stdio.h>

int main(void)
{
  printf("/developer/cbook/.......................\n");
  printf("по правому краю: %8d\n", 100);
  printf(" по левому краю: %-8d\n", 100);

  return 0;
}

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

.........................
по правому краю:      100
 по левому краю: 100

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


Некоторые модификаторы в вызове функции 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.

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

#include <stdio.h>

int main(void)
{
  printf("%x %#x\n", 10, 10);
  printf("%*.*f", 10, 4, 1234.34);

  return 0;
}
printf("%*.*f", 10.4, 123.3);
         | |     |     |
         '-+-----'     |
           |           |
           '-----------'

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

----------
[1]Часто называется просто форматной строкой, форматным стрингом или форматом.
[2]Называются также спецификациями формата.
[3]Называются также спецификаторами.