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 ; |
(depuis 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 ; |
(depuis 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 ; |
(depuis 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,
|
(depuis 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 classe la plus dérivée.
La conversion se déroule en trois étapes :
Table des matières |
Étape 1 : sélection du spécificateur de conversion
- Les indicateurs de format d'E/S sont obtenus, comme si par
- fmtflags basefield = ( str. flags ( ) & std:: ios_base :: basefield ) ;
- fmtflags boolalpha = ( str. flags ( ) & std:: ios_base :: boolalpha ) ;
`, `
` et `
- Si le type de v est un type entier, le premier choix applicable parmi les cinq suivants est sélectionné :
- Si basefield == oct , utilisera le spécificateur de conversion % o
- Si basefield == hex , utilisera le spécificateur de conversion % X
- Si basefield == 0 , utilisera le spécificateur de conversion % i
- Si le type de v est signé, utilisera le spécificateur de conversion % d
- Si le type de v est non signé, utilisera le spécificateur de conversion % u
- Pour les types entiers, le modificateur de longueur est ajouté à la spécification de conversion si nécessaire : h pour short et unsigned short , l pour long et unsigned long , ll pour long long et unsigned long long (depuis C++11)
- Si le type de v est float , la spécificateur de conversion % g sera utilisé
- Si le type de v est double , la spécificateur de conversion % lg sera utilisé
- Si le type de v est long double , la spécificateur de conversion % Lg sera utilisé
- Si le type de v est void * , la spécificateur de conversion % p sera utilisé
- Si le type de v est bool et boolalpha == 0 , procède comme si le type de v était long , sauf pour la valeur à stocker dans v à l'étape 3.
-
Si le type de
v
est
bool
et
boolalpha
!
=
0
, les étapes 2 et 3 sont remplacées par :
- Les caractères successifs obtenus de l'itérateur d'entrée in sont comparés aux séquences de caractères obtenues de std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . falsename ( ) et std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . truename ( ) uniquement dans la mesure nécessaire pour identifier la correspondance unique. L'itérateur d'entrée in est comparé à end uniquement lorsque nécessaire pour obtenir un caractère.
- Si la séquence cible est identifiée de manière unique, v est défini sur la valeur bool correspondante. Sinon, false est stocké dans v et std::ios_base::failbit est assigné à err . Si aucune correspondance unique n'a pu être trouvée avant la fin de l'entrée ( in == end ), err | = std:: ios_base :: eofbit est exécuté.
Étape 2 : extraction des caractères
- Si in == end , l'étape 2 se termine immédiatement, aucun caractère supplémentaire n'est extrait.
-
Le caractère suivant est extrait de
in
comme par
char_type ct
=
*
in
;
:
- Si le caractère correspond à l'un de "0123456789abcdefxABCDEFX+-" (jusqu'à C++11) "0123456789abcdefpxABCDEFPX+-" (depuis C++11) , élargi au char_type de la locale comme par std:: use_facet < std:: ctype < CharT >> ( str. getloc ( ) ) . widen ( ) , il est converti en char correspondant.
- Si le caractère correspond au séparateur décimal ( std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . decimal_point ( ) ) ), il est remplacé par '.' .
- Si le caractère correspond au séparateur de milliers ( std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . thousands_sep ( ) ) et que la séparation des milliers est utilisée (déterminée par std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . grouping ( ) . length ( ) ! = 0 ), alors si le point décimal '.' n'a pas encore été accumulé, la position du caractère est mémorisée, mais le caractère est autrement ignoré. Si le point décimal a déjà été accumulé, le caractère est rejeté et l'étape 2 se termine.
- Dans tous les cas, une vérification est effectuée pour déterminer si le char obtenu des étapes précédentes est autorisé dans le champ d'entrée qui serait analysé par std::scanf étant donné le spécificateur de conversion sélectionné à l'étape 1. S'il est autorisé, il est accumulé dans un tampon temporaire et l'étape 2 se répète. S'il n'est pas autorisé, l'étape 2 se termine.
Étape 3 : conversion et stockage
- La séquence de char s accumulée dans l'étape 2 est convertie en une valeur numérique :
|
(jusqu'en C++11) |
|
(depuis C++11) |
- Si la fonction de conversion échoue à convertir l'intégralité du champ, la valeur 0 est stockée dans v .
- Si le type de v est un type entier signé et que la fonction de conversion produit une valeur positive ou négative trop grande pour y tenir, la valeur représentable la plus positive ou la plus négative est stockée dans v , respectivement.
- Si le type de v est un type entier non signé et que la fonction de conversion produit une valeur qui n'y tient pas, la valeur représentable la plus positive est stockée dans v .
- Dans tous les cas, si la fonction de conversion échoue std::ios_base::failbit est assigné à err .
-
Sinon, le résultat numérique de la conversion est stocké dans
v
.
- Si le type de v est bool et que boolalpha n'est pas défini, alors si la valeur à stocker est 0 , false est stocké, si la valeur à stocker est 1 , true est stocké, pour toute autre valeur std::ios_base::failbit est assigné à err et true est stocké.
- Ensuite, le regroupement de chiffres est vérifié. si la position de l'un des séparateurs de milliers ignorés lors de l'étape 2 ne correspond pas au regroupement fourni par std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . grouping ( ) , std::ios_base::failbit est assigné à err .
- Si l'étape 2 a été terminée par le test in == end , err | = std:: ios_base :: eofbit est exécuté pour définir le bit eof.
Valeur de retour
in
Notes
Avant les résolutions de LWG issue 23 et LWG issue 696 , v restait inchangé si une erreur se produit.
Avant la résolution de
LWG issue 221
, les chaînes représentant des entiers hexadécimaux (par exemple
"0xA0"
) étaient rejetées par
do_get(int)
même si elles constituent une entrée valide pour
strtol
car l'étape 2 filtre les caractères
'X'
et
'x'
.
Avant la résolution de LWG issue 1169 , la conversion d'une chaîne de nombre négatif en entier non signé pouvait produire zéro (car la valeur représentée par la chaîne est inférieure à ce que le type cible peut représenter).
|
Avant la résolution de
LWG issue 2381
, les chaînes représentant des nombres hexadécimaux à virgule flottante avec exposants (par exemple
"0x1.23p-10"
) étaient rejetées par
Les chaînes représentant l'infini ou NaN (par exemple
"NaN"
et
"inf"
) sont rejetées par
|
(depuis C++11) |
Exemple
Une implémentation de
operator>>
pour un type défini par l'utilisateur.
#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; }
Rapports de défauts
Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.
| DR | Appliqué à | Comportement publié | Comportement corrigé |
|---|---|---|---|
| LWG 17 | C++98 | le processus d'analyse des valeurs booléennes textuelles était erroné | corrigé |
| LWG 18 | C++98 |
la surcharge de
get
prenant une valeur
bool
&
était manquante
|
ajoutée |
| LWG 23 | C++98 | un dépassement en entrée entraînait un comportement indéfini | dépassement géré |
| LWG 154 | C++98 | le spécificateur de conversion pour double était % g (identique à float ) | changé en % lg |
| LWG 221 | C++98 |
do_get
n'analysait pas
'x'
et
'X'
alors que
strtol
les analysait
|
rendu 'x' et 'X' analysés |
| LWG 275 | C++98 |
get
avait une surcharge prenant une valeur
short
&
au lieu de
float
&
|
corrigé |
| LWG 358 | C++98 | les séparateurs de milliers après la virgule décimale étaient ignorés | l'étape 2 est terminée si rencontrés |
| LWG 696 | C++98 | le résultat restait inchangé en cas d'échec de conversion | mis à zéro |
| LWG 1169 | C++98 | la gestion du dépassement était incohérente entre les types à virgule flottante |
rendue cohérente
avec
strtof
/
strtod
|
| LWG 2381 | C++11 |
do_get
n'analysait pas
'p'
et
'P'
alors que
strtod
les analysait
|
rendu 'p' et 'P' analysés |
Voir aussi
|
extrait des données formatées
(fonction membre publique de
std::basic_istream<CharT,Traits>
)
|