Spec-Zone.ru › C++

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) (начиная с 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) (начиная с 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) (начиная с 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) (начиная с 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)
1-11) Открытая функция-член, вызывает функцию-член do_get наиболее производного класса.
12-22) Считывает символы из входного итератора 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 и unsignedshort, l для long и unsignedlong, ll для longlong и unsignedlonglong(начиная с C++11)
  • Если тип v — float, используется спецификатор преобразования %g
  • Если тип v — double, используется спецификатор преобразования %lg
  • Если тип v — longdouble, используется спецификатор преобразования %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. В противном случае false сохраняется в v, а std::ios_base::failbit присваивается err. Если до конца ввода (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, накопленная на этапе 2, преобразуется в числовое значение:
Ввод разбирается согласно правилам std::scanf. (до C++11)
  • std::strtoll для знакового целого числа v,
  • std::strtoull для беззнакового целого числа v,
  • std::strtof для float v,
  • std::strtod для double v или
  • std::strtold для long double v.
(начиная с 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 23 и вопросу LWG 696 значение v оставалось неизменным при возникновении ошибки.

До принятия решения по вопросу LWG 221 строки, представляющие шестнадцатеричные целые числа (например, "0xA0"), отклонялись функцией do_get(int), даже если являлись допустимым вводом для strtol, поскольку на этапе 2 символы 'X' и 'x' отфильтровываются.

До принятия решения по вопросу LWG 1169 преобразование строки с отрицательным числом в беззнаковое целое число могло давать ноль (поскольку значение, представленное строкой, меньше того, которое может представить целевой тип).

До принятия решения по вопросу LWG 2381 строки, представляющие шестнадцатеричные числа с плавающей точкой с экспонентами (например, "0x1.23p-10"), отклонялись функцией do_get(double), даже если являлись допустимым вводом для strtod, поскольку на этапе 2 символы 'P' и 'p' отфильтровываются.

Строки, представляющие бесконечность или значение «не число» (например, "NaN" и "inf"), отклоняются функцией do_get(double), даже если являются допустимым вводом для strtod, поскольку на этапе 2 отфильтровываются такие символы, как 'N' или 'i'.

(начиная с 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'

См. также

operator>>
извлекает форматированные данные
(открытая функция-член std::basic_istream<CharT,Traits>)

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/locale/num_get/get

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API