Способы форматирования вывода с

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

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

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

Функция форматированного вывода printf получает в качестве аргументов строку формат и аргументы, которые необходимо вывести в соответствии с форматом, и возвращает число выведенных символов. В случае ошибки возвращает отрицательное значение и устанавливает значение ferror. Если произошло несколько ошибок, errno равно EILSEQ.
int printf (const char * format, . );

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

Общий синтаксис спецификатора формата
%[флаги][ширина][.точность][длина]спецификатор
Спецификатор – это самый важный компонент. Он определяет тип переменной и способ её вывода.

Таб. 1 Спецификатор типа.

Спецификатор Что хотим вывести Пример
d или i Целое со знаком в в десятичном виде 392
u Целое без знака в десятичном виде 7235
o Беззнаковое в восьмеричном виде 657
x Беззнаковое целое в шестнадцатеричном виде 7fa
X Беззнаковое целое в шестнадцатеричном виде, верхний регистр 7FA
f или F Число с плавающей точкой 3.4563745
e Экспоненциальная форма для числа с плавающей точкой 3.1234e+3
E Экспоненциальная форма для числа с плавающей точкой, верхний регистр 3.1234E+3
g Кратчайшее из представлений форматов f и e 3.12
G Кратчайшее из представлений форматов F и E 3.12
a Шестнадцатеричное представление числа с плавающей точкой -0xc.90fep-2
A Шестнадцатеричное представление числа с плавающей точкой, верхний регистр -0xc.90FEP-2
c Буква a
s Строка (нуль-терминированный массив букв) Hello World
p Адрес указателя b8000000
n Ничего не печатает. Аргументом должен быть указатель на signed int. По этому адресу будет сохранено количество букв, которое было выведено до встречи %n
% Два идущих друг за другом процента выводят знак процента %

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

Таб. 2 Флаги.

Флаг Описание
Выключка влево на заданное шириной значение
+ Явно указывать знак у числа, даже для положительных чисел
(пробел) Если знак не будет выведен, то вставляет пробел перед выводимым числом
# Когда используется вместе с o, x или X, вставляет перед числом 0, 0x или 0X
Когда используется со спецификаторами a, A, e, E, f, F, g или G, вставляет десятичную точку, даже если после неё нет десятичных знаков.
0 Вставляет нули, когда объявлен спецификатор ширины
Таб. 3 Ширина.
Ширина Описание
(число) Минимальное количество знаков, которое необходимо вывести. Если в числе меньше знаков, то вставляет пробелы (или нули)
* Ширина не указана в строке формата, она передаётся отдельно в виде аргумента, который должен предшествовать выводимому числу
Таб. 4 Точность.
.Точность Описание
.число Для спецификаторов целых (d, i, o, u, x, X) точность определяет минимальное количество знаков, которое необходимо вывести. Если значение короче, то выводятся нули перед числом. Значение не обрезается, даже если оно длиннее. Точночть 0 означает, что для значения 0 ничего не выводится.
Для спецификаторов чисел с плавающей точкой (a, A, e, E, f, F) это число знаков, которые необходимо вывести после десятичной точки (по умолчанию 6).
Для g и G — это число значащих разрядов, которые необходимо вывести.
Для s — выводится указанное число символов. По умолчанию выводятся все символы до первого нулевого.
Если число не стоит, то по умолчанию точность равна 0
.* Точность не указана в строке формата, она передаётся отдельно в виде аргумента, который должен предшествовать выводимому числу

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

Таб. 5 Длина.

спецификаторы
Длина d, i u o x X f F e E g G a A c s p n
(none) int unsigned int double int char* void* int*
hh signed char unsigned char signed char*
h short int unsigned short int short int*
l long int unsigned long int wint_t wchar_t* long int*
ll long long int unsigned long long int long long int*
j intmax_t uintmax_t intmax_t*
z size_t size_t size_t*
t ptrdiff_t ptrdiff_t ptrdiff_t*
L long double

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

Рассмотрим форматированный ввод функцией scanf.
int scanf(const char*, . )
Функция принимает строку формата ввода (она похожа на строку формата printf) и адреса, по которым необходимо записать считанные данные. Возвращает количество успешно проинициализированных аргументов.
Формат спецификатора ввода
%[*][ширина][длинна]спецификатор

Таб. 6 Спецификатор типа.

Спецификатор Описание Выбранные символы
i, u Целые Произвольное число цифр (0-9), возможно, начинающихся с + или -. Если число начинается с 0, то считывается в восьмеричном формате, если с 0x, то в шестнадцатеричном.
d Десятичное целое Произвольное число цифр (0-9), возможно, начинающихся с + или -.
o восьмеричное целое Произвольное число цифр (0-7), возможно, начинающихся с + или -.
x Шестнадцатеричное целое Произвольное число цифр (0-F), возможно, начинающихся с + или — и префикса 0x или 0X.
f, e, g Число с плавающей точкой Число, состоящее из набора цифр 0-9, возможно с десятичным разделителем (точкой). Возможно также представление в экспоненциальной форме. C99 позволяет также вводить число в шестнадцатеричном формате.
a
c Символ Если ширина не передана, то считывает один символ. Если ширина передана, то считывает нужное количество символов и размещает их в массиве БЕЗ терминального символа на конце.
s Строка Считывает все не пробельные символы. Если указана ширина, то не более n символов. Ставит на место n+1 символа терминальный.
p Адрес указателя Последовательность символов, трактуемая как адрес указателя. Формат зависит от реализации, но совпадает с тем, как выводит printf с ключом p
[символы] Множество символов Считывает только те символы, которые записаны в квадратных скобках, С99
[^символы] Множество символов Считывает только те символы, которые не указаны в квадратных скобках, С99
n Ничего не считывает Сохраняет число уже считанных символов по указанному адресу

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

Кроме функций scanf и printf есть ещё ряд функций, которые позволяют получать вводимые данные

int getch() [aka _getch(), getchar()] — возвращает введённый символ, при этом не выводит его на консоль.

char * fgets ( char * str, int num, FILE * stream ) — функция позволяет считывать строку с пробельными символами. Несмотря на то, что она работает с файлом, можно с её помощью считывать и из стандартного потока ввода. Её преимущество относительно gets в том, что она позволяет указать максимальный размер считываемой строки и заканчивает строку терминальным символом.

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

Непечатные символы

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

Источник

Форматирование строк и ввода-вывода (современный C++)

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

Этот подход является типобезопасным и расширяемым, но он также является сложным и подробным.

Альтернативные параметры формата

В качестве альтернативы можно использовать Boost.Format из библиотеки Boost C++, даже если она нестандартна. Вы можете скачать любую библиотеку Boost с веб-сайта Boost .

Некоторые преимущества Boost.Format :

Сейф: строго типизированный и вызывает исключение для ошибок, например спецификацию слишком мало или слишком много элементов.

Расширяемый: работает для любого типа, который может быть потоковым.

Удобно: стандартные POSIX и строки формата.

Хотя Boost.Format основана на средствах C++, которые являются надежными и расширяемыми, они не оптимизированы для производительности. При необходимости оптимизации производительности рассмотрите возможность использования функций printf и sprintf, которые быстро и просты в использовании. Однако они не являются расширяемыми и не защищены от уязвимостей. (Сейф версии существуют, но это существенно снижает производительность. Дополнительные сведения см. в разделе printf_s, _printf_s_l, wprintf_s, _wprintf_s_l и sprintf_s, _sprintf_s_l, swprintf_s, _swprintf_s_l).

В следующем коде показаны некоторые функции форматирования, повышающие эффективность.

Источник

Урок №209. Функционал классов ostream и ios. Форматирование вывода

Обновл. 15 Сен 2021 |

На этом уроке мы рассмотрим функционал классов ostream и ios в языке С++.

Примечание: Весь функционал объектов, которые работают с потоками ввода/вывода, находится в пространстве имен std. Это означает, что вам нужно либо добавлять префикс std:: ко всем объектам и функциям ввода/вывода, либо использовать в программе строку using namespace std; .

Форматирование вывода

Оператор вставки (вывода) используется для помещения информации в выходной поток. А как мы уже знаем из урока о потоках, классы istream и ostream являются дочерними классу ios . Одной из задач ios (и ios_base ) является управление параметрами форматирования вывода.

Есть два способа управления параметрами форматирования вывода:

флаги — это логические переменные, которые можно включить/выключить;

манипуляторы — это объекты, которые помещаются в поток и влияют на способ ввода/вывода данных.

Для включения флага используйте функцию setf() с соответствующим флагом в качестве параметра. Например, по умолчанию C++ не выводит знак + перед положительными числами. Однако, используя флаг std::showpos, мы можем это изменить:

Также можно включить сразу несколько флагов, используя побитовый оператор ИЛИ ( | ):

Чтобы отключить флаг, используйте функцию unsetf():

Многие флаги принадлежат к определенным группам форматирования. Группа форматирования — это группа флагов, которые задают аналогичные (иногда взаимоисключающие) параметры форматирования вывода. Например, есть группа форматирования basefield.

Флаги группы форматирования basefield:

oct (от англ. «octal» = «восьмеричный») — восьмеричная система счисления;

dec (от англ. «decimal» = «десятичный») — десятичная система счисления;

hex (от англ. «hexadecimal» = «шестнадцатеричный») — шестнадцатеричная система счисления.

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

Ничего не работает! Почему? Дело в том, что setf() только включает флаги, он не настолько умен, чтобы одновременно отключать другие (взаимоисключающие) флаги. Следовательно, когда мы включаем std::hex, std::dec также включен и у него приоритет выше. Есть два способа решения данной проблемы.

Во-первых, мы можем отключить std::dec, а затем включить std::hex:

Теперь уже результат тот, что нужно:

Второй способ — использовать вариацию функции setf(), которая принимает два параметра:

первый параметр — это флаг, который нужно включить/выключить;

второй параметр — группа форматирования, к которой принадлежит флаг.

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

Язык C++ также предоставляет еще один способ изменения параметров форматирования: манипуляторы. Фишка манипуляторов в том, что они достаточно умны, чтобы одновременно включать и выключать соответствующие флаги. Например:

В общем, использовать манипуляторы гораздо проще, нежели включать/выключать флаги. Многие параметры форматирования можно изменять как через флаги, так и через манипуляторы, но есть и такие параметры форматирования, которые изменить можно либо только через флаги, либо только через манипуляторы.

Полезные флаги, манипуляторы и методы

Ниже мы рассмотрим список наиболее полезных флагов, манипуляторов и методов. Флаги находятся в классе ios , манипуляторы — в пространстве имен std, а методы — в классе ostream .

Флаг:

boolalpha — если включен, то логические значения выводятся как true / false . Если выключен, то логические значения выводятся как 0 / 1 .

Манипуляторы:

boolalpha — логические значения выводятся как true / false .

noboolalpha — логические значения выводятся как 0 / 1 .

1 0
true false
1 0
true false

Флаг:

showpos — если включен, то перед положительными числами указывается знак + .

Манипуляторы:

showpos — перед положительными числами указывается знак + .

noshowpos — перед положительными числами не указывается знак + .

Флаг:

uppercase — если включен, то используются заглавные буквы.

Манипуляторы:

uppercase — используются заглавные буквы.

nouppercase — используются строчные буквы.

1.23457e+007
1.23457E+007
1.23457e+007
1.23457E+007

Флаги группы форматирования basefield:

dec — значения выводятся в десятичной системе счисления;

hex — значения выводятся в шестнадцатеричной системе счисления;

oct — значения выводятся в восьмеричной системе счисления.

Манипуляторы:

dec — значения выводятся в десятичной системе счисления;

hex — значения выводятся в шестнадцатеричной системе счисления;

oct — значения выводятся в восьмеричной системе счисления.

Теперь вы уже должны понимать связь между флагами и манипуляторами.

Точность, запись чисел и десятичная точка

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

Флаги группы форматирования floatfield:

fixed — используется десятичная запись чисел типа с плавающей точкой;

scientific — используется экспоненциальная запись чисел типа с плавающей точкой;

showpoint — всегда отображается десятичная точка и конечные нули для чисел типа с плавающей точкой.

Манипуляторы:

fixed — используется десятичная запись значений;

scientific — используется экспоненциальная запись значений;

showpoint — отображается десятичная точка и конечные нули чисел типа с плавающей точкой;

noshowpoint — не отображаются десятичная точка и конечные нули чисел типа с плавающей точкой;

setprecision(int) — задаем точность для чисел типа с плавающей точкой.

Методы:

precision() — возвращаем текущую точность для чисел типа с плавающей точкой;

precision(int) — задаем точность для чисел типа с плавающей точкой.

Если используется десятичная или экспоненциальная запись чисел, то точность определяет количество цифр после запятой/точки. Обратите внимание, если точность меньше количества значащих цифр, то число будет округлено. Например:

Источник

Читайте также:  Предмет от способа отличие
Оцените статью
Разные способы