std::num_put<CharT,OutputIt>:: put, std::num_put<CharT,OutputIt>:: do_put
|
Definido en el encabezado
<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 ; |
(desde 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 ; |
(desde 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 ; |
(desde 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 ; |
(desde 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
de la clase más derivada.
La conversión ocurre en cuatro etapas:
Contenidos |
Etapa 1: selección del especificador de conversión
- Los indicadores de formato de E/S se obtienen, como si fuera mediante
- 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 ) ;
-
Si el tipo de
val
es
bool
:
- Si boolalpha == 0 , entonces convierte val al tipo int y realiza salida de entero.
- Si boolalpha ! = 0 , obtiene std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . truename ( ) si val == true o std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . falsename ( ) si val == false , y envía cada carácter sucesivo c de esa cadena a out con * out ++ = c . No se realiza más procesamiento en este caso, la función retorna out .
-
Si el tipo de
val
es un tipo entero, se selecciona la primera opción aplicable de las siguientes:
- Si basefield == oct , usará el especificador de conversión % o .
- Si basefield == hex && ! uppercase , usará el especificador de conversión % x .
- Si basefield == hex , usará el especificador de conversión % X .
- Si el tipo de val es con signo, usará el especificador de conversión % d .
- Si el tipo de val es sin signo, usará el especificador de conversión % u .
- Para tipos enteros, se añade el modificador de longitud a la especificación de conversión si es necesario: l para long y unsigned long , ll para long long y unsigned long long (desde C++11) .
- Si el tipo de val es un tipo de punto flotante, se selecciona la primera opción aplicable de las siguientes:
|
(hasta C++11) |
|
(desde C++11) |
-
- Si floatfield == std:: ios_base :: scientific && ! uppercase , utilizará el especificador de conversión % e .
- Si floatfield == std:: ios_base :: scientific , utilizará el especificador de conversión % E .
|
(desde C++11) |
-
- Si ! uppercase , utilizará el especificador de conversión % g .
- En caso contrario, utilizará el especificador de conversión % G .
-
Además:
- Si el tipo de val es long double , se añade el modificador de longitud L al especificador de conversión.
- Si el tipo de val es un tipo de punto flotante y floatfield ! = ( ios_base :: fixed | ios_base :: scientific ) (desde C++11) , se añade el modificador de precisión y se establece en str. precision ( ) . En caso contrario, no se especifica precisión.
- Para tipos enteros y de punto flotante, si showpos está activado, el modificador + se antepone.
- Para tipos enteros, si showbase está activado, el modificador # se antepone.
- Para tipos de punto flotante, si showpoint está activado, el modificador # se antepone.
- Si el tipo de val es void * , se utilizará el especificador de conversión % p
- Una cadena de caracteres estrechos se crea como si mediante una llamada a std:: printf ( spec, val ) en la configuración regional "C", donde spec es el especificador de conversión elegido.
Etapa 2: conversión específica de la configuración regional
-
Cada carácter
c
obtenido en la Etapa 1, excepto el punto decimal
'.'
, se convierte a
CharTllamando a std:: use_facet < std:: ctype < CharT >> ( str. getloc ( ) ) . widen ( c ) . - Para tipos aritméticos, el carácter separador de miles, obtenido de std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . thousands_sep ( ) , se inserta en la secuencia según las reglas de agrupamiento proporcionadas por std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . grouping ( ) .
- Los caracteres de punto decimal ( '.' ) se reemplazan por std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . decimal_point ( ) .
Etapa 3: padding
-
La bandera de ajuste se obtiene como si fuera mediante
std
::
fmtflags
adjustfield
=
(
flags
&
(
std::
ios_base
::
adjustfield
)
)
y se examina para identificar la ubicación del relleno, como sigue:
- Si adjustfield == std:: ios_base :: left , rellenará después.
- Si adjustfield == std:: ios_base :: right , rellenará antes.
- Si adjustfield == std:: ios_base :: internal y ocurre un carácter de signo en la representación, rellenará después del signo.
- Si adjustfield == std:: ios_base :: internal y la representación de la Etapa 1 comenzó con 0x o 0X, rellenará después de la x o X.
- En caso contrario, rellenará antes.
-
Si
str.
width
(
)
es distinto de cero (por ejemplo, se acaba de usar
std::setw
) y el número de
CharTdespués de la Etapa 2 es menor que str. width ( ) , entonces se insertan copias del carácter de relleno fill en la posición indicada por el relleno para llevar la longitud de la secuencia a str. width ( ) .
En cualquier caso, str. width ( 0 ) se llama para cancelar los efectos de std::setw .
Etapa 4: salida
Cada carácter sucesivo
c
de la secuencia de
CharT
's de la Etapa 3 se emite como si fuera mediante
*
out
++
=
c
.
Parámetros
| out | - | iterador que apunta al primer carácter que será sobrescrito |
| str | - | flujo del cual obtener la información de formato |
| fill | - | carácter de relleno utilizado cuando los resultados necesitan ser ajustados al ancho del campo |
| val | - | valor a convertir a cadena y mostrar |
Valor de retorno
out
Notas
El cero inicial generado por la especificación de conversión #o (resultante de la combinación de std::showbase y std::oct por ejemplo) no se cuenta como un carácter de relleno.
|
Al formatear un valor de punto flotante como hexfloat (es decir, cuando floatfield == ( std:: ios_base :: fixed | std:: ios_base :: scientific ) ), la precisión del flujo no se utiliza; en su lugar, el número siempre se imprime con suficiente precisión para representar exactamente el valor. |
(since C++11) |
Ejemplo
Mostrar un número usando el facet directamente, y demostrar un facet definido por el usuario:
#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'; }
Salida:
2.71 36 144
Una implementación de operator<< para un tipo definido por el usuario.
#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; }
Salida:
10
Informes de defectos
Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C++ publicados anteriormente.
| DR | Se aplica a | Comportamiento publicado | Comportamiento correcto |
|---|---|---|---|
| LWG 34 | C++98 |
la sobrecarga de
bool
utilizaba miembros inexistentes
truename y falsename de std::ctype |
utiliza estos miembros
de std::numpunct |
| LWG 231 | C++98 |
el modificador de precisión solo se añadía si
( flags & fixed ) ! = 0 o str. precision ( ) > 0 |
eliminó estas condiciones |
| LWG 282 | C++98 |
los separadores de miles solo se
insertaban para tipos integrales en la etapa 2 |
también se insertan para
tipos de punto flotante |
| LWG 4084 | C++11 | "NAN" y "INF" no se podían imprimir | se pueden imprimir |
Véase también
|
inserta datos formateados
(función miembro pública de
std::basic_ostream<CharT,Traits>
)
|