std::num_get<CharT,InputIt>::get, std::num_get<CharT,InputIt>::do_get
public:
iter_type get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, bool& v ) const;
|
(1) | |
iter_type get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, long& v ) const;
|
(2) | |
iter_type get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, long long& v ) const;
|
(3) | (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;
|
(4) | |
iter_type get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, unsigned int& v ) const;
|
(5) | |
iter_type get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, unsigned long& v ) const;
|
(6) | |
iter_type get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, unsigned long long& v ) const;
|
(7) | (since C++11) |
iter_type get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, float& v ) const;
|
(8) | |
iter_type get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, double& v ) const;
|
(9) | |
iter_type get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, long double& v ) const;
|
(10) | |
iter_type get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, void*& v ) const;
|
(11) | |
protected:
virtual iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, bool& v ) const;
|
(12) | |
virtual iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, long& v ) const;
|
(13) | |
virtual iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, long long& v ) const;
|
(14) | (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;
|
(15) | |
virtual iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, unsigned int& v ) const;
|
(16) | |
virtual iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, unsigned long& v ) const;
|
(17) | |
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;
|
(18) | (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;
|
(19) | |
virtual iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, double& v ) const;
|
(20) | |
virtual iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, long double& v ) const;
|
(21) | |
virtual iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, void*& v ) const;
|
(22) | |
do_get наиболее производного класса.in и генерирует значение типа v, учитывая флаги форматирования потока ввода/вывода из str.flags(), правила классификации символов из std::use_facet<std::ctype<CharT>>(str.getloc()) и символы числовой пунктуации из std::use_facet<std::numpunct<CharT>>(str.getloc()). Эта функция вызывается всеми операторами форматированного ввода, такими как std::cin >> n;.Преобразование происходит в три этапа:
Этап 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>
)
|