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 ; |
(начиная с 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 ; |
(начиная с 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 ; |
(начиная с 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,
|
(начиная с 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
наиболее производного класса.
Преобразование происходит в три этапа:
Содержание |
Этап 1: выбор спецификатора преобразования
- Флаги формата ввода-вывода получаются, как если бы
- fmtflags basefield = ( str. flags ( ) & std:: ios_base :: basefield ) ;
- fmtflags boolalpha = ( str. flags ( ) & std:: ios_base :: boolalpha ) ;
- Если тип v является целочисленным, выбирается первый применимый вариант из следующих пяти:
- Если basefield == oct , будет использоваться спецификатор преобразования % o
- Если basefield == hex , будет использоваться спецификатор преобразования % X
- Если basefield == 0 , будет использоваться спецификатор преобразования % i
- Если тип v является знаковым, будет использоваться спецификатор преобразования % d
- Если тип v является беззнаковым, будет использоваться спецификатор преобразования % u
- Для целочисленных типов модификатор длины добавляется к спецификатору преобразования при необходимости: h для short и unsigned short , l для long и unsigned long , ll для long long и unsigned long long (начиная с C++11)
- Если тип v — float , будет использоваться спецификатор преобразования % g
- Если тип v — double , будет использоваться спецификатор преобразования % lg
- Если тип v — long double , будет использоваться спецификатор преобразования % Lg
- Если тип v — void * , будет использоваться спецификатор преобразования % p
- Если тип v — bool и boolalpha == 0 , выполняется так, как если бы тип v был long , за исключением значения, которое будет сохранено в v на этапе 3.
-
Если тип
v
—
bool
и
boolalpha
!
=
0
, следующие этапы заменяют этапы 2 и 3:
- Последовательные символы, полученные из входного итератора in , сопоставляются с последовательностями символов, полученными из std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . falsename ( ) и std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . truename ( ) только в той мере, в какой это необходимо для идентификации уникального совпадения. Входной итератор in сравнивается с end только при необходимости получения символа.
- Если целевая последовательность однозначно совпадает, v устанавливается в соответствующее значение bool . В противном случае в v сохраняется false , и в err устанавливается std::ios_base::failbit . Если уникальное совпадение не было найдено до окончания ввода ( in == end ), выполняется err | = std:: ios_base :: eofbit .
Этап 2: извлечение символов
- Если in == end , этап 2 немедленно завершается, дальнейшие символы не извлекаются.
-
Следующий символ извлекается из
in
как если бы с помощью
char_type ct
=
*
in
;
:
- Если символ совпадает с одним из "0123456789abcdefxABCDEFX+-" (до C++11) "0123456789abcdefpxABCDEFPX+-" (начиная с C++11) , расширенным до char_type локали как если бы с помощью std:: use_facet < std:: ctype < CharT >> ( str. getloc ( ) ) . widen ( ) , он преобразуется в соответствующий char .
- Если символ совпадает с разделителем десятичной точки ( std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . decimal_point ( ) ) ), он заменяется на '.' .
- Если символ совпадает с разделителем тысяч ( std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . thousands_sep ( ) ) и используется разделение тысяч (как определено с помощью std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . grouping ( ) . length ( ) ! = 0 ), тогда если десятичная точка '.' еще не была накоплена, позиция символа запоминается, но символ в остальном игнорируется. Если десятичная точка уже была накоплена, символ отбрасывается и этап 2 завершается.
- В любом случае проверяется, разрешен ли char , полученный на предыдущих шагах, во входном поле, которое будет разбираться с помощью std::scanf с учетом спецификатора преобразования, выбранного на этапе 1. Если разрешен, он накапливается во временном буфере и этап 2 повторяется. Если не разрешен, этап 2 завершается.
Этап 3: преобразование и хранение
- Последовательность char s, накопленная на этапе 2, преобразуется в числовое значение:
|
(до C++11) |
|
(начиная с C++11) |
- Если функция преобразования не может преобразовать всё поле, значение 0 сохраняется в v .
- Если тип v является знаковым целочисленным типом и функция преобразования возвращает положительное или отрицательное значение, слишком большое для этого типа, в v сохраняется максимально возможное положительное или отрицательное представимое значение соответственно.
- Если тип v является беззнаковым целочисленным типом и функция преобразования возвращает значение, которое не помещается в него, в v сохраняется максимально возможное положительное представимое значение.
- В любом случае, если функция преобразования завершается неудачно, std::ios_base::failbit присваивается err .
-
В противном случае числовой результат преобразования сохраняется в
v
.
- Если тип v — bool и boolalpha не установлен, то если сохраняемое значение равно 0 , сохраняется false , если сохраняемое значение равно 1 , сохраняется true , для любого другого значения std::ios_base::failbit присваивается err и сохраняется true .
- После этого проверяется группировка цифр. Если позиция любого из разделителей тысяч, отброшенных на этапе 2, не соответствует группировке, предоставляемой std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . grouping ( ) , std::ios_base::failbit присваивается err .
- Если этап 2 был завершён проверкой in == end , выполняется err | = std:: ios_base :: eofbit для установки бита eof.
Возвращаемое значение
in
Примечания
До разрешения LWG issue 23 и LWG issue 696 , v оставался неизменным в случае возникновения ошибки.
До разрешения
LWG issue 221
, строки, представляющие шестнадцатеричные целые числа (например,
"0xA0"
), отклонялись функцией
do_get(int)
даже если они являются допустимым вводом для
strtol
, поскольку этап 2 отфильтровывает символы
'X'
и
'x'
.
До разрешения LWG issue 1169 , преобразование строки с отрицательным числом в беззнаковое целое могло приводить к нулю (поскольку значение, представленное строкой, меньше того, которое может представить целевой тип).
|
До решения
проблемы LWG 2381
строки, представляющие шестнадцатеричные числа с плавающей точкой с экспонентами (например,
"0x1.23p-10"
), отклонялись методом
Строки, представляющие бесконечность или не-число (например,
"NaN"
и
"inf"
), отклоняются методом
|
(начиная с C++11) |
Пример
Реализация оператора
operator>>
для пользовательского типа.
#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; }
Отчеты о дефектах
Следующие отчеты об изменениях в поведении, содержащие описания дефектов, были применены ретроактивно к ранее опубликованным стандартам C++.
| DR | Применено к | Поведение в опубликованной версии | Исправленное поведение |
|---|---|---|---|
| LWG 17 | C++98 | процесс разбора текстовых булевых значений содержал ошибки | исправлено |
| LWG 18 | C++98 |
перегрузка
get
принимающая
bool
&
значение отсутствовала
|
добавлена |
| LWG 23 | C++98 | переполнение ввода приводило к неопределенному поведению | переполнение обрабатывается |
| LWG 154 | C++98 | спецификатор преобразования для double был % g (такой же как для float ) | изменен на % lg |
| LWG 221 | C++98 |
do_get
не разбирал
'x'
и
'X'
тогда как
strtol
разбирал их
|
сделано так, чтобы 'x' и 'X' разбирались |
| LWG 275 | C++98 |
get
имел перегрузку принимающую
short
&
вместо
float
&
|
исправлено |
| LWG 358 | C++98 | разделители тысяч после десятичной точки игнорировались | этап 2 завершается при их обнаружении |
| LWG 696 | C++98 | результат не изменялся при неудачном преобразовании | устанавливается в ноль |
| LWG 1169 | C++98 | обработка переполнения была несогласованной между типами с плавающей точкой |
сделана согласованной
с
strtof
/
strtod
|
| LWG 2381 | C++11 |
do_get
не разбирал
'p'
и
'P'
тогда как
strtod
разбирал их
|
сделано так, чтобы 'p' и 'P' разбирались |
Смотрите также
|
извлекает форматированные данные
(публичная функция-член
std::basic_istream<CharT,Traits>
)
|