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,
char_type fill, bool val ) const;
| ||
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,
char_type fill, bool val ) const;
| ||
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 самого производного класса.out, которые представляют значение val, отформатированное в соответствии с заданными флагами форматирования str.flags(), и компонентами std::numpunct и std::ctype области локали, установленной в потоке str. Эта функция вызывается всеми операторами форматированного вывода потока, такими как std::cout << n;.Преобразование происходит в четырёх этапах:
Этап 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является типом с плавающей точкой, выбирается первый применимый вариант из следующего:- Если
floatfield == std::ios_base::fixed, используется спецификатор преобразования%f - Если
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: выравнивание
- Флаг выравнивания получается как если бы это было
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) не считается символом выравнивания.
| При форматировании значения с плавающей точкой в виде шестнадцатеричной плавающей точки (т.е., когда | (с 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, base const& 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 | также добавлять для чисел с плавающей точкой |
См. также
| вставляет отформатированные данные (публичный член-функция std::basic_ostream<CharT,Traits>) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/locale/num_put/put