Далее приведен еще один пример:
char initial = 'А';
char *surname = "Matthew";
double age = 13.5;
printf("Hello Mr %c %s, aged %g\n", initial, surname, age);
Будет выводиться следующая информация:
Hello Mr A Matthew, aged 13.5
Вы можете добиться большего при выводе элементов с помощью спецификаторов полей. Они расширяют возможности спецификаторов преобразований, управляя расположением элементов при выводе. Обычно задается количество десятичных разрядов для числа с плавающей точкой или величина пробельных отступов, обрамляющих строку.
Спецификаторы полей задаются в виде чисел, следующих в спецификаторах преобразований непосредственно за знаком %. В табл. 3.5 приведены дополнительные примеры использования спецификаторов преобразований и результирующий вывод. Для большей ясности мы применяем знак вертикальной черты, чтобы показать границы вывода.
Таблица 3.5
| Формат | Аргумент | Вывод |
|---|---|---|
%10s
|
"Hello"
|
| Hello|
|
%-10s
|
"Hello"
|
|Hello |
|
%10d
|
1234
|
| 1234|
|
%-10d
|
1234
|
|1234 |
|
%010d
|
1234
|
|0000001234|
|
%10.4f
|
12.34
|
| 12.3400|
|
%*s
|
10, "Hello"
|
| Hello|
|
Все приведенные примеры выводятся в поле шириной 10 символов. Обратите внимание на то, что отрицательная ширина поля означает выравнивание элемента по левому краю в пределах поля. Переменная ширина поля обозначается символом "звездочка" (*). В этом случае следующий аргумент применяется для задания ширины. Ведущий ноль указывает на вывод элемента с ведущими нулями. В соответствии со стандартом POSIX функция printf не обрезает поля; наоборот она расширяет поле, чтобы вместить в него аргумент. Например, если вы попытаетесь вывести строку большей длины, чем заданное поле, ширина поля будет увеличена (табл. 3.6).
Таблица 3.6
| Формат | Аргумент | Вывод |
|---|---|---|
%10s
|
"HelloTherePeeps"
|
|HelloTherePeeps|
|
Функции семейства printf возвращают целое число, равное количеству выведенных символов. В случае функции sprintf в него не включается завершающий нуль-символ. При наличии ошибок эти функции возвращают отрицательное значение и задают переменную errno.
scanf, fscanf и sscanf
Семейство функций scanf действует аналогично функциям группы printf за исключением того, что эти функции читают элементы из потока и помещают их в переменные, адреса которых им передаются как параметры-указатели. Для управления преобразованиями ввода функции применяют строку format аналогичным образом и используют многие спецификаторы преобразований функций группы printf.
#include <stdio.h>
int scanf(const char *format, ...);
int fscanf(FILE *stream, const char *format, ...);
int sscanf(const char *s, const char *format, ...);
Очень важно, чтобы переменные, используемые для хранения значений, считываемых функциями scanf, имели корректный тип и точно соответствовали строке формата. Если это не так, используемая память может быть искажена и программа может завершиться аварийно. При этом не будет обнаружено никаких ошибок компиляции. Если повезет, вы можете получить предупреждающее сообщение!
Строка format функции scanf и других функций этого семейства, как и в случае функции printf, содержит как обычные символы, так и спецификаторы преобразований. Но обычные символы применяются для задания символов, которые должны присутствовать во вводе.
Рассмотрим простой пример:
int num;
scanf("Hello %d", &num);
Вызов функции scanf будет успешным, только если следующие пять символов в стандартном вводе — Hello. Затем, если следующие символы формируют распознаваемое десятичное число, оно будет считано и присвоено переменной num. Пробел в строке формата при вводе применяется для игнорирования во вводном файле всех пробельных символов (пробелы, табуляции, переводы страницы и переходы на новую строку) между спецификаторами преобразований. Это означает, что вызов, scanf будет успешным и поместит 1234 в переменную num в случае следующих двух вариантов ввода.
Hello 1234
Hellol234
Пробельные символы обычно игнорируются во вводе, когда начинается преобразование. Это означает, что строка формата %d будет продолжать чтение из вводного файла, пропуская пробелы и переходы на новую строку до тех пор, пока будет продолжаться цифровая последовательность. Если ожидаемые символы отсутствуют, преобразование аварийно завершается и выполнение функции прекращается.