std::num_get<CharT,InputIt>:: get, std::num_get<CharT,InputIt>:: do_get
| (1) | ||
|
public
:
iter_type get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
|
||
|
iter_type get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, long & v ) const ; |
||
|
iter_type get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, long long & v ) const ; |
(desde C++11) | |
|
iter_type get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, unsigned short & v ) const ; |
||
|
iter_type get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, unsigned int & v ) const ; |
||
|
iter_type get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, unsigned long & v ) const ; |
||
|
iter_type get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, unsigned long long & v ) const ; |
(desde C++11) | |
|
iter_type get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, float & v ) const ; |
||
|
iter_type get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, double & v ) const ; |
||
|
iter_type get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, long double & v ) const ; |
||
|
iter_type get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, void * & v ) const ; |
||
| (2) | ||
|
protected
:
virtual
iter_type do_get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
|
||
|
virtual
iter_type do_get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, long & v ) const ; |
||
|
virtual
iter_type do_get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, long long & v ) const ; |
(desde C++11) | |
|
virtual
iter_type do_get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, unsigned short & v ) const ; |
||
|
virtual
iter_type do_get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, unsigned int & v ) const ; |
||
|
virtual
iter_type do_get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, unsigned long & v ) const ; |
||
|
virtual
iter_type do_get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std::
ios_base
::
iostate
&
err,
|
(desde C++11) | |
|
virtual
iter_type do_get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, float & v ) const ; |
||
|
virtual
iter_type do_get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, double & v ) const ; |
||
|
virtual
iter_type do_get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, long double & v ) const ; |
||
|
virtual
iter_type do_get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, void * & v ) const ; |
||
do_get
de la clase más derivada.
La conversión ocurre en tres 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 boolalpha = ( str. flags ( ) & std:: ios_base :: boolalpha ) ;
- Si el tipo de v es un tipo entero, se selecciona la primera opción aplicable de las siguientes cinco:
- Si basefield == oct , utilizará el especificador de conversión % o
- Si basefield == hex , utilizará el especificador de conversión % X
- Si basefield == 0 , utilizará el especificador de conversión % i
- Si el tipo de v es con signo, utilizará el especificador de conversión % d
- Si el tipo de v es sin signo, utilizará 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: h para short y unsigned short , l para long y unsigned long , ll para long long y unsigned long long (desde C++11)
- Si el tipo de v es float , se usará el especificador de conversión % g
- Si el tipo de v es double , se usará el especificador de conversión % lg
- Si el tipo de v es long double , se usará el especificador de conversión % Lg
- Si el tipo de v es void * , se usará el especificador de conversión % p
- Si el tipo de v es bool y boolalpha == 0 , procede como si el tipo de v fuera long , excepto por el valor a almacenar en v en la etapa 3.
-
Si el tipo de
v
es
bool
y
boolalpha
!
=
0
, lo siguiente reemplaza las etapas 2 y 3:
- Los caracteres sucesivos obtenidos del iterador de entrada in se comparan con las secuencias de caracteres obtenidas de std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . falsename ( ) y std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . truename ( ) solo según sea necesario para identificar la coincidencia única. El iterador de entrada in se compara con end solo cuando es necesario obtener un carácter.
- Si la secuencia objetivo coincide de forma única, v se establece al valor bool correspondiente. De lo contrario, se almacena false en v y se asigna std::ios_base::failbit a err . Si no se pudo encontrar una coincidencia única antes de que terminara la entrada ( in == end ), se ejecuta err | = std:: ios_base :: eofbit .
Etapa 2: extracción de caracteres
- Si in == end , la etapa 2 termina inmediatamente, no se extraen más caracteres.
-
El siguiente carácter se extrae de
in
como si fuera mediante
char_type ct
=
*
in
;
:
- Si el carácter coincide con alguno de "0123456789abcdefxABCDEFX+-" (hasta C++11) "0123456789abcdefpxABCDEFPX+-" (desde C++11) , ensanchado al char_type de la localización como si fuera mediante std:: use_facet < std:: ctype < CharT >> ( str. getloc ( ) ) . widen ( ) , se convierte al char correspondiente.
- Si el carácter coincide con el separador decimal ( std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . decimal_point ( ) ) ), se reemplaza por '.' .
- Si el carácter coincide con el separador de miles ( std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . thousands_sep ( ) ) y la separación de miles está en uso (determinado por std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . grouping ( ) . length ( ) ! = 0 ), entonces si el punto decimal '.' aún no ha sido acumulado, se recuerda la posición del carácter, pero el carácter se ignora en lo demás. Si el punto decimal ya ha sido acumulado, el carácter se descarta y la etapa 2 termina.
- En cualquier caso, se verifica si el char obtenido de los pasos anteriores está permitido en el campo de entrada que sería analizado por std::scanf dada la especificación de conversión seleccionada en la etapa 1. Si está permitido, se acumula en un búfer temporal y la etapa 2 se repite. Si no está permitido, la etapa 2 termina.
Etapa 3: conversión y almacenamiento
- La secuencia de char s acumulada en la etapa 2 se convierte en un valor numérico:
|
(hasta C++11) |
|
(desde C++11) |
- Si la función de conversión falla al convertir el campo completo, el valor 0 se almacena en v .
- Si el tipo de v es un tipo entero con signo y la función de conversión produce un valor positivo o negativo demasiado grande para caber en él, se almacena el valor representable más positivo o más negativo en v , respectivamente.
- Si el tipo de v es un tipo entero sin signo y la función de conversión produce un valor que no cabe en él, se almacena el valor representable más positivo en v .
- En cualquier caso, si la función de conversión falla std::ios_base::failbit se asigna a err .
-
De lo contrario, el resultado numérico de la conversión se almacena en
v
.
- Si el tipo de v es bool y boolalpha no está establecido, entonces si el valor a almacenar es 0 , false se almacena, si el valor a almacenar es 1 , true se almacena, para cualquier otro valor std::ios_base::failbit se asigna a err y true se almacena.
- Después de esto, se verifica el agrupamiento de dígitos. si la posición de cualquiera de los separadores de miles descartados en la etapa 2 no coincide con el agrupamiento proporcionado por std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . grouping ( ) , std::ios_base::failbit se asigna a err .
- Si la etapa 2 fue terminada por la prueba in == end , err | = std:: ios_base :: eofbit se ejecuta para establecer el bit eof.
Valor de retorno
in
Notas
Antes de las resoluciones de LWG issue 23 y LWG issue 696 , v permanecía sin cambios si ocurría un error.
Antes de la resolución de
LWG issue 221
, las cadenas que representaban enteros hexadecimales (por ejemplo,
"0xA0"
) eran rechazadas por
do_get(int)
incluso si eran entradas válidas para
strtol
porque la etapa 2 filtraba los caracteres
'X'
y
'x'
.
Antes de la resolución de LWG issue 1169 , convertir una cadena de número negativo en un entero sin signo podría producir cero (ya que el valor representado por la cadena es menor de lo que el tipo destino puede representar).
|
Antes de la resolución de
LWG issue 2381
, las cadenas que representaban números de punto flotante hexadecimales con exponentes (por ejemplo,
"0x1.23p-10"
) eran rechazadas por
Las cadenas que representaban infinito o no es un número (por ejemplo,
"NaN"
y
"inf"
) eran rechazadas por
|
(desde C++11) |
Ejemplo
Una implementación de
operator>>
para un tipo definido por el usuario.
#include <iostream> #include <iterator> #include <locale> struct base { long x; }; template<class CharT, class Traits> std::basic_istream<CharT, Traits>& operator >>(std::basic_istream<CharT, Traits>& is, base& b) { std::ios_base::iostate err = std::ios_base::goodbit; try // setting err could throw { typename std::basic_istream<CharT, Traits>::sentry s(is); if (s) // if stream is ready for input std::use_facet<std::num_get<CharT>>(is.getloc()).get(is, {}, is, err, b.x); } catch (std::ios_base::failure& error) { // handle the exception } return is; } int main() { base b; std::cin >> b; }
Informes de defectos
Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C++ publicados anteriormente.
| DR | Aplicado a | Comportamiento publicado | Comportamiento correcto |
|---|---|---|---|
| LWG 17 | C++98 | el proceso de análisis de valores booleanos de texto era erróneo | corregido |
| LWG 18 | C++98 |
faltaba la sobrecarga de
get
que toma valor
bool
&
|
añadida |
| LWG 23 | C++98 | el desbordamiento de entrada resultaba en comportamiento indefinido | desbordamiento manejado |
| LWG 154 | C++98 | el especificador de conversión para double era % g (igual que para float ) | cambiado a % lg |
| LWG 221 | C++98 |
do_get
no analizaba
'x'
y
'X'
mientras que
strtol
sí los analizaba
|
se hizo que 'x' y 'X' sean analizados |
| LWG 275 | C++98 |
get
tenía una sobrecarga que tomaba valor
short
&
en lugar de
float
&
|
corregido |
| LWG 358 | C++98 | los separadores de miles después del punto decimal eran ignorados | la etapa 2 termina si se encuentran |
| LWG 696 | C++98 | el resultado permanecía sin cambios en fallo de conversión | establecido a cero |
| LWG 1169 | C++98 | el manejo de desbordamiento era inconsistente entre tipos de punto flotante |
hecho consistente
con
strtof
/
strtod
|
| LWG 2381 | C++11 |
do_get
no analizaba
'p'
y
'P'
mientras que
strtod
sí los analizaba
|
se hizo que 'p' y 'P' sean analizados |
Véase también
|
extrae datos formateados
(función miembro pública de
std::basic_istream<CharT,Traits>
)
|