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, std::ios_base::iostate& err, bool& v ) const; |
||
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; |
(since 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; |
(since 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, std::ios_base::iostate& err, bool& v ) const; |
||
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; |
(since 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, unsigned long long& v ) const; |
(since 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
of the most derived class.
in
and generates the value of the type of
v
, taking into account IO stream formatting flags from
str.flags()
, character classification rules from
std::use_facet<std::ctype<charT>>(str.getloc())
, and numeric punctuation characters from
std::use_facet<std::numpunct<charT>>(str.getloc())
. This function is called by all formatted input stream operators such as
std::cin >> n;
.
Conversion occurs in three stages.
Stage 1: conversion specifier selection
- I/O format flags are obtained, as if by
-
fmtflags basefield = (str.flags() & std::ios_base::basefield);
-
fmtflags boolalpha = (str.flags() & std::ios_base::boolalpha);
- If the type of
v
is an integer type, the first applicable choice of the following five is selected:
-
If
basefield == oct
, will use conversion specifier%o
-
If
basefield == hex
, will use conversion specifier%X
-
If
basefield == 0
, will use conversion specifier%i
-
If the type of
v
is signed, will use conversion specifier%d
-
If the type of
v
is unsigned, will use conversion specifier%u
- For integer types, length modifier is added to the conversion specification if necessary:
h
forshort
andunsigned short
,l
forlong
andunsigned long
,ll
forlong long
andunsigned long long
- If the type of
v
isfloat
, will use conversion specifier%g
- If the type of
v
isdouble
, will use conversion specifier%lg
- If the type of
v
islong double
, will use conversion specifier%Lg
- If the type of
v
isvoid*
, will use conversion specifier%p
- If the type of
v
isbool
andboolalpha==0
, proceeds as if the type ofv
islong
, except for the value to be stored inv
in stage 3. - If the type of
v
isbool
andboolalpha!=0
, the following replaces stages 2 and 3:- Successive characters obtained from the input iterator
in
are matched against the character sequences obtained fromstd::use_facet<std::numpunct<charT>>(str.getloc()).falsename()
andstd::use_facet<std::numpunct<charT> >(str.getloc()).truename()
only as necessary as to identify the unique match. The input iteratorin
is compared toend
only when necessary to obtain a character. - If the target sequence is uniquely matched,
v
is set to the correspondingbool
value. Otherwisefalse
is stored inv
andstd::ios_base::failbit
is assigned toerr
. If unique match could not be found before the input ended (in==end
),err|=std::ios_base::eofbit
is executed.
- Successive characters obtained from the input iterator
Stage 2: character extraction
- If
in==end
, Stage 2 is terminated immediately, no further characters are extracted - The next character is extracted from
in
as if bychar_type ct = *in;
- If the character matches one of
"0123456789abcdefxABCDEFX+-"
(until C++11)"0123456789abcdepfxABCDEFPX+-"
(since C++11), widened to the locale's char_type as if bystd::use_facet<std::ctype<charT>>(str.getloc()).widen()
, it is converted to the correspondingchar
. - If the character matches the decimal point separator (
std::use_facet<std::numpunct<charT>>(str.getloc()).decimal_point())
), it is replaced by'.'
. - If the character matches the thousands separator (
std::use_facet<std::numpunct<charT>>(str.getloc()).thousands_sep()
) and the thousands separation is in use (as determined bystd::use_facet<std::numpunct<charT>>(str.getloc()).grouping().length() != 0
), then if the decimal point'.'
has not yet been accumulated, the position of the character is remembered, but the character is otherwise ignored. If the decimal point has already been accumulated, the character is discarded and Stage 2 terminates. - In any case, the check is made whether the
char
obtained from the previous steps is allowed in the input field that would be parsed bystd::scanf
given the conversion specifier selected in Stage 1. If it is allowed, it is accumulated in a temporary buffer and Stage 2 repeats. If it is not allowed, Stage 2 terminates.
- If the character matches one of
Stage 3: conversion and storage
- The sequence of
char
s accumulated in Stage 2 is converted to a numeric value
std::strtoll
for signed integer
v
,
std::strtoull
for unsigned integer
v
,
std::strtof
for
float
v
,
std::strtod
for
double
v
, or
std::strtold
for
long double
v
- If the conversion function fails to convert the entire field, the value
0
is stored inv
- If the type of
v
is a signed integer type and the conversion function results in a positive or negative value too large to fit in it, the most positive or negative representable value is stored inv
, respectively - If the type of
v
is an unsigned integer type and the conversion function results in a value that does not fit in it, the most positive representable value is stored inv
. - In any case, if the conversion function fails
std::ios_base::failbit
is assigned toerr
- Otherwise, the numeric result of the conversion is stored in
v
- If the type of
v
isbool
and boolalpha is not set, then if the value to be stored is0
,false
is stored, if the value to be stored is1
,true
is stored, for any other valuestd::ios_base::failbit
is assigned toerr
andtrue
is stored.
- If the type of
- After this, digit grouping is checked. if the position of any of the thousands separators discarded in Stage 2 does not match the grouping provided by
std::use_facet<std::numpunct<charT>>(str.getloc()).grouping()
,std::ios_base::failbit
is assigned toerr
. - If Stage 2 was terminated by the test
in==end
,err|=std::ios_base::eofbit
is executed to set the eof bit.
Return value
in
.
Notes
C++98/C++03 specified that v
is left unchanged if an error occurs. Such behavior is corrected by LWG23 and LWG696 which are merged into C++11.
When converting a negative number string into an unsigned integer, some implementations produce zero (since the value represented by the string is smaller than what the target type can represent). Such behavior was specified in C++11/14 standard but is corrected by LWG1169.
Because stage 2 filters out characters such as 'N'
or 'i'
, the strings "NaN"
or "inf"
is rejected by do_get(double)
even if they are valid input to strtod
. Hexadecimal floating-point numbers such "0x1.23p-10"
used to be rejected by do_get
, which is a defect fixed by LWG2381.
Example
An implementation of operator>>
for a user-defined type.
#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; }
Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
LWG 23 | C++98 | overflowing input resulted in undefined behavior | overflow handled |
LWG 696 | C++98 | the result was unchanged on conversion failure | set to zero |
LWG 1169 | C++98 | overflow handling was inconsistent between floating-point types | made consistent with strtof /strtod |
LWG 2381 | C++11 | do_get did not parse 'p' and 'P' while strtod parsed them |
made 'p' and 'P' parsed |
See also
extracts formatted data (public member function of std::basic_istream<CharT,Traits> ) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/locale/num_get/get