% [flags] [width] [.precision] [F | N | h | l | L ] <символ типа>
Опции flags могут определять выравнивание, отображение знака числа при выводе, вывод десятичной точки и символов заполнения. Кроме того, эти флаги определяют префиксы для восьмеричных и шестнадцатеричных чисел. Возможные значения флагов приведены в таблице 2.
Таблица 7.2. Значения флагов строки формата функции printf
Символ | Назначение |
- | Выравнивать вывод по левому краю поля |
+ | Всегда выводить знак числа |
Пробел | Выводить пробел перед положительным числом и знак минус — перед отрицательным |
# | Не влияет на вывод десятичных целых, для шестнадцатеричных чисел выводит префикс 0х или 0Х, перед восьмеричными целыми выводит ноль, десятичную точку для вещественных чисел. |
Спецификация width определяет минимальное количество выводимых символов. Если необходимо, используются заполнители — пробелы или нули. Когда значение для width начинается с нуля, printf использует в качестве заполнителей нули, а не пробелы. Если в качестве значения для width используется универсальный символ *, а не число, то printf подставляет на место этого символа значение, которое должно содержаться в списке аргументов. Это значение ширины поля должно предшествовать выводимому значению. Ниже приведен пример вывода числа 2, занимающего три позиции, согласно значению второго аргумента printf:
printf("%*d", 3, 2);
Спецификатор precision определяет максимальное количество выводимых цифр. В случае целого числа он определяет минимальное количество выводимых символов. Для precision также можно применить символ *, вместо которого будет подставлено значение из списка аргументов. Это значение точности представления должно предшествовать выводимому значению. Ниже приведен пример вывода числа с плавающей точкой 3.3244 с использованием десяти символов, как это задано вторым аргументом printf:
printf("%7.*f", 10, 3.3244);
Символы F, N, h,l и L являются символами размера, переопределяющими размер по умолчанию. Символы F и N применяются с указателями, far и near соответственно. Символы h, l, и L используются для указания соответственно типов short int, long или long double.
Символам типа данных должен предшествовать форматирующий символ %. В таблице 7.2 мы показали возможные значения флагов форматирующей строки printf. Символы типов данных перечислены в таблице 7.3.
Таблица 3. Символы типов данных строки формата функции printf
Тип данных | символ типа | результат |
Символ | c | Один символ |
d | Десятичное целое со знаком | |
i | Десятичное целое со знаком | |
O | Восьмеричное целое без знака | |
N | Десятичное целое без знака | |
X | Шестнадцатеричное целое без знака; набор цифр - 0123456789abcdef | |
X | Шестнадцатеричное целое без знака; набор цифр - 0123456789ABCDEF | |
Указатель | P | Для указателей near выводит только смещение в виде: 0000. Указатели far отображаются в виде: SSSS:0000 |
Указательна целое | N | |
Вещественное | F | Выводит величину со знаком в формате [-]dddd.dddd |
E | Выводит вещественную величину со знаком в экспоненциальном формате [-]d.dddde[+|-]ddd | |
Е | Выводит вещественную величину со знаком в экспоненциальном формате [-]d.ddddE[+|-]ddd | |
G | Выводит вещественную величину со знаком в формате f или е в зависимости от ее значения и заданной точности | |
G | Выводит вещественную величину со знаком в формате F или Е в зависимости от ее значения и заданной точности | |
Указатель | S | Выводит строку символов, пока не встретит нуль-терминатор строки |
Разберем небольшой пример. Программа OUT2.CPP, исходный код которой приведен в листинге 3, создана на основе программы OUT1.CPP. В этой программе используется форматированный вывод с использованием функции printf. Программа выводит те же числа, что и OUT1.CPP, используя три различных набора спецификаций преобразования.
Листинг 3. Исходный текст программы OUT2.CPP в файле List7-3.CPP
01 | // Программа, использующая printf для форматирования вывода |
02 | |
03 | #include <stdio.h> |
04 | |
05 | int main() |
06 | { |
07 | int anInt = 67; |
08 | Unsigned char aByte = 128; |
09 | char aChar = '@'; |
10 | Float aSingle = 355.0; |
11 | Double aDouble = 1.130e+002; |
12 | |
13 | Printf("%3d + %2d = %3d\n", |
14 | aByte, anInt, aByte + anInt ); |
15 | |
16 | Printf("Вывод использует спецификации преобразования %%lf :\n"); |
17 | Printf(" %6.4f / %10.4lf = %7.5lf\n", |
18 | aSingle, aDouble, aSingle / aDouble ); |
19 | |
20 | Printf("Вывод использует спецификации преобразования %%le :\n"); |
21 | printf(" %6.4e / %6.4le = %7.5le\n", |
22 | aSingle, aDouble, aSingle / aDouble ); |
23 | |
24 | printf("Вывод использует спецификации преобразования %%lg :\n"); |
25 | printf(" %6.4g / %6.4lg = %7.5lg\n", |
26 | aSingle, aDouble, aSingle / aDouble ); |
27 | |
28 | printf("Символьная переменная aChar: %c\n", aChar); |
29 | printf("ASCII-код %c: %d\n", aChar, aChar); |
30 | return 0; |
31 | } |
Пример вывода программы из листинга 3:
128 + 67 = 195
Вывод использует спецификации преобразования %lf :
355.0000 / 113.0000 = 3.14159
Вывод использует спецификации преобразования %le :
3.5500e+02 / 1.1300e+02 = 3.14159e+00
Вывод использует спецификации преобразования %lg :
355 / 113 = 3.1416
Символьная переменная aChar: @
ASCII-код @: 64
В программе из листинга 3 объявляется целый набор переменных различных типов. Оператор вывода в строках 13 и 14 выводит целые, используя спецификацию формата %d. В таблице 4 приведены результаты действия спецификаций преобразования из строки 13. Обратите внимание на то, что первая переменная была преобразована из типа unsigned char в тип integer.
Таблица 4. Результат действия спецификаций форматирования в функции printf из строки 13
Спецификация формата | Переменная | Тип данных | Тип после преобразования |
%3d | aByte | unsigned char | Int |
%2d | anInt | int | Int |
%3d | aByte + anInt | int | Int |
Оператор вывода в строке 17 выводит переменные aSingle, aDouble и выражение aSingle / aDouble, используя спецификации преобразования %6.4f, %6.41f и % 7.51f. Точность представления задается ими равной 4, 4 и 5 цифрам, а минимальная ширина поля 6, 6 и 7 цифрам соответственно. Две последних спецификации осуществляют преобразование величин двойной точности.
Оператор вывода в строке 21 подобен оператору из строки 17. Отличие состоит в том, что используется е-формат вместо f-формата. Соответственно три значения выводятся в экспоненциальном формате.
Оператор из строки 25 также похож на оператор из строки 17. Основное отличие состоит в том, что вместо f-формата используется g-формат. В результате первые два числа выводятся без дробной части, поскольку они являются целыми величинами.
Оператор вывода в строке 28 выводит содержимое переменной aChar по формату %с. Оператор вывода в строке 29 выводит ту же переменную aChar дважды, первый раз как символ, а второй раз как целое (или, если быть точным, выводится ASCII-код символа). Для этого используются спецификации преобразования %с и %d соответственно.
Массивы символов в C++
В C++ имеется специальный класс для работы со строками, которого, конечно, не было в языке С. В С строки вводились как массивы символов, ограниченные нуль-символом (ASCII-код которого равен нулю), поэтому большое количество программ, написанных на С, используют символьные массивы. Более того, и в C++, несмотря на то, что он имеет класс для работы со строками, находится применение массивам символов. Поэтому термин “строка” имеет два значения: строка в смысле C++ и строка как массив символов. Весь этот раздел будет посвящен тому, как нужно и не нужно использовать символьные массивы.
Символ '\0' также называют нуль-терминатором. Строки, оканчивающиеся нуль-терминатором, называют еще ASCIIZ-строками, гдесимвол Z обозначает ноль — ASCII-код нуль-терминатора. Еще этот символ называют NUL-символом, поскольку этот термин является его именем в ASCII.
Все строки обязательно должны оканчиваться нуль-терминатором, и при объявлении размера массива необходимо это учитывать. Когда вы объявляете строковую переменную как массив символов, увеличьте размер массива на один символ для нуль-терминатора. Использование строк с конечным нулем также имеет то преимущество, что здесь отсутствуют ограничения, накладываемые реализацией C++. Кроме того, структура ASCIIZ-строк очень проста.
В программах, которые мы рассматривали, операторы потокового вывода выводили строковые константы; C++ поддерживает потоковый вывод для строк как специального не-предопределенного типа данных. (Можно сказать, что это было сделано по требованию масс.) Операции и синтаксис для вывода строковых переменных остаются прежними. При вводе строк операция извлечения из потока ” не всегда будет работать так, как вы ожидаете, поскольку строки часто содержат пробелы, которые игнорируются оператором ввода; поэтому вместо оператора ввода вам нужно использовать функцию getline. Эта функция вводит заданное количество символов.