std::num_put<CharT,OutputIt>:: put, std::num_put<CharT,OutputIt>:: do_put
|
Определено в заголовке
<locale>
|
||
| (1) | ||
|
public
:
iter_type put
(
iter_type out,
std::
ios_base
&
str,
|
||
|
iter_type put
(
iter_type out,
std::
ios_base
&
str,
char_type fill, long val ) const ; |
||
|
iter_type put
(
iter_type out,
std::
ios_base
&
str,
char_type fill, long long val ) const ; |
(начиная с C++11) | |
|
iter_type put
(
iter_type out,
std::
ios_base
&
str,
char_type fill, unsigned long val ) const ; |
||
|
iter_type put
(
iter_type out,
std::
ios_base
&
str,
char_type fill, unsigned long long val ) const ; |
(начиная с C++11) | |
|
iter_type put
(
iter_type out,
std::
ios_base
&
str,
char_type fill, double val ) const ; |
||
|
iter_type put
(
iter_type out,
std::
ios_base
&
str,
char_type fill, long double val ) const ; |
||
|
iter_type put
(
iter_type out,
std::
ios_base
&
str,
char_type fill, const void * val ) const ; |
||
| (2) | ||
|
protected
:
virtual
iter_type do_put
(
iter_type out,
std::
ios_base
&
str,
|
||
|
virtual
iter_type do_put
(
iter_type out,
std::
ios_base
&
str,
char_type fill, long val ) const ; |
||
|
virtual
iter_type do_put
(
iter_type out,
std::
ios_base
&
str,
char_type fill, long long val ) const ; |
(начиная с C++11) | |
|
virtual
iter_type do_put
(
iter_type out,
std::
ios_base
&
str,
char_type fill, unsigned long val ) const ; |
||
|
virtual
iter_type do_put
(
iter_type out,
std::
ios_base
&
str,
char_type fill, unsigned long long val ) const ; |
(начиная с C++11) | |
|
virtual
iter_type do_put
(
iter_type out,
std::
ios_base
&
str,
char_type fill, double val ) const ; |
||
|
virtual
iter_type do_put
(
iter_type out,
std::
ios_base
&
str,
char_type fill, long double val ) const ; |
||
|
virtual
iter_type do_put
(
iter_type out,
std::
ios_base
&
str,
char_type fill, const void * val ) const ; |
||
do_put
самого производного класса.
Преобразование происходит в четыре этапа:
Содержание |
Этап 1: выбор спецификатора преобразования
- Флаги формата ввода-вывода получаются, как если бы с помощью
- fmtflags basefield = ( str. flags ( ) & std:: ios_base :: basefield ) ;
- fmtflags uppercase = ( str. flags ( ) & std:: ios_base :: uppercase ) ;
- fmtflags floatfield = ( str. flags ( ) & std:: ios_base :: floatfield ) ;
- fmtflags showpos = ( str. flags ( ) & std:: ios_base :: showpos ) ;
- fmtflags showbase = ( str. flags ( ) & std:: ios_base :: showbase ) ;
- fmtflags showpoint = ( str. flags ( ) & std:: ios_base :: showpoint ) ;
-
Если тип
val
является
bool
:
- Если boolalpha == 0 , преобразует val в тип int и выполняет целочисленный вывод.
- Если boolalpha ! = 0 , получает std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . truename ( ) если val == true или std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . falsename ( ) если val == false , и выводит каждый последующий символ c этой строки в out с помощью * out ++ = c . В этом случае дальнейшая обработка не выполняется, функция возвращает out .
-
Если тип
val
является целочисленным типом, выбирается первый применимый вариант из следующих:
- Если basefield == oct , будет использоваться спецификатор преобразования % o .
- Если basefield == hex && ! uppercase , будет использоваться спецификатор преобразования % x .
- Если basefield == hex , будет использоваться спецификатор преобразования % X .
- Если тип val знаковый, будет использоваться спецификатор преобразования % d .
- Если тип val беззнаковый, будет использоваться спецификатор преобразования % u .
- Для целочисленных типов модификатор длины добавляется к спецификации преобразования при необходимости: l для long и unsigned long , ll для long long и unsigned long long (начиная с C++11) .
- Если тип val является типом с плавающей точкой, выбирается первый применимый вариант из следующих:
|
(до C++11) |
|
(начиная с C++11) |
-
- Если floatfield == std:: ios_base :: scientific && ! uppercase , будет использоваться спецификатор преобразования % e .
- Если floatfield == std:: ios_base :: scientific , будет использоваться спецификатор преобразования % E .
|
(начиная с C++11) |
-
- Если ! uppercase , будет использован спецификатор преобразования % g .
- Иначе будет использован спецификатор преобразования % G .
-
Также:
- Если тип val — long double , к спецификатору преобразования добавляется модификатор длины L .
- Если тип val является типом с плавающей точкой и floatfield ! = ( ios_base :: fixed | ios_base :: scientific ) (начиная с C++11) , добавляется модификатор точности, устанавливаемый в значение str. precision ( ) . В противном случае точность не указывается.
- Для целочисленных и типов с плавающей точкой, если установлен showpos , модификатор + добавляется в начало.
- Для целочисленных типов, если установлен showbase , модификатор # добавляется в начало.
- Для типов с плавающей точкой, если установлен showpoint , модификатор # добавляется в начало.
- Если тип val является void * , будет использоваться спецификатор преобразования % p
- Строка узких символов создаётся как при вызове std:: printf ( spec, val ) в локали "C", где spec — выбранный спецификатор преобразования.
Этап 2: преобразование с учетом локали
-
Каждый символ
c
полученный на Этапе 1, кроме десятичной точки
'.'
, преобразуется в
CharTвызовом std:: use_facet < std:: ctype < CharT >> ( str. getloc ( ) ) . widen ( c ) . - Для арифметических типов символ разделителя тысяч, полученный из std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . thousands_sep ( ) , вставляется в последовательность согласно правилам группировки, предоставляемым std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . grouping ( ) .
- Символы десятичной точки ( '.' ) заменяются на std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . decimal_point ( ) .
Этап 3: padding
-
Флаг выравнивания получается как будто бы с помощью
std
::
fmtflags
adjustfield
=
(
flags
&
(
std::
ios_base
::
adjustfield
)
)
и анализируется для определения позиции заполнения следующим образом:
- Если adjustfield == std:: ios_base :: left , заполнение будет после значения.
- Если adjustfield == std:: ios_base :: right , заполнение будет перед значением.
- Если adjustfield == std:: ios_base :: internal и в представлении встречается символ знака, заполнение будет после знака.
- Если adjustfield == std:: ios_base :: internal и представление на Этапе 1 начиналось с 0x или 0X, заполнение будет после x или X.
- В противном случае заполнение будет перед значением.
-
Если
str.
width
(
)
не равно нулю (например, только что использовался
std::setw
) и количество символов
CharTпосле Этапа 2 меньше, чем str. width ( ) , тогда копии символа fill вставляются в позицию, указанную для заполнения, чтобы довести длину последовательности до str. width ( ) .
В любом случае, str. width ( 0 ) вызывается для отмены эффектов std::setw .
Этап 4: вывод
Каждый последующий символ
c
из последовательности
CharT
из Стадии 3 выводится как если бы выполнялось
*
out
++
=
c
.
Параметры
| out | - | итератор, указывающий на первый символ для перезаписи |
| str | - | поток для получения информации о форматировании |
| fill | - | символ заполнения, используемый при необходимости дополнения результатов до ширины поля |
| val | - | значение для преобразования в строку и вывода |
Возвращаемое значение
out
Примечания
Ведущий ноль, сгенерированный спецификацией преобразования #o (результат комбинации std::showbase и std::oct например) не считается символом заполнения.
|
При форматировании значения с плавающей точкой в виде шестнадцатеричного представления (т.е. когда floatfield == ( std:: ios_base :: fixed | std:: ios_base :: scientific ) ), точность потока не используется; вместо этого число всегда выводится с достаточной точностью для точного представления значения. |
(since C++11) |
Пример
Вывод числа напрямую с использованием фасета и демонстрация пользовательского фасета:
#include <iostream> #include <locale> // this custom num_put outputs squares of all integers (except long long) struct squaring_num_put : std::num_put<char> { iter_type do_put(iter_type out, std::ios_base& str, char_type fill, long val) const { return std::num_put<char>::do_put(out, str, fill, val * val); } iter_type do_put(iter_type out, std::ios_base& str, char_type fill, unsigned long val) const { return std::num_put<char>::do_put(out, str, fill, val * val); } }; int main() { auto& facet = std::use_facet<std::num_put<char>>(std::locale()); facet.put(std::cout, std::cout, '0', 2.71); std::cout << '\n'; std::cout.imbue(std::locale(std::cout.getloc(), new squaring_num_put)); std::cout << 6 << ' ' << -12 << '\n'; }
Вывод:
2.71 36 144
Реализация operator<< для пользовательского типа.
#include <iostream> #include <iterator> #include <locale> struct base { long x = 10; }; template<class CharT, class Traits> std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const base& b) { try { typename std::basic_ostream<CharT, Traits>::sentry s(os); if (s) { std::ostreambuf_iterator<CharT, Traits> it(os); std::use_facet<std::num_put<CharT>>(os.getloc()) .put(it, os, os.fill(), b.x); } } catch (...) { // set badbit on os and rethrow if required } return os; } int main() { base b; std::cout << b; }
Вывод:
10
Отчёты о дефектах
Следующие отчеты об изменениях в поведении, содержащие описания дефектов, были применены ретроактивно к ранее опубликованным стандартам C++.
| DR | Применяется к | Поведение в опубликованной версии | Корректное поведение |
|---|---|---|---|
| LWG 34 | C++98 |
перегрузка для
bool
использовала несуществующие члены
truename и falsename из std::ctype |
использовать эти члены
из std::numpunct |
| LWG 231 | C++98 |
модификатор точности добавлялся только если
( flags & fixed ) ! = 0 или str. precision ( ) > 0 |
убраны эти условия |
| LWG 282 | C++98 |
разделители тысяч вставлялись только
для целочисленных типов на этапе 2 |
также вставляются для
типов с плавающей точкой |
| LWG 4084 | C++11 | "NAN" и "INF" не могли быть выведены | они могут быть выведены |
Смотрите также
|
вставляет форматированные данные
(публичная функция-член
std::basic_ostream<CharT,Traits>
)
|