Namespaces
Variants

std::num_get<CharT,InputIt>::get, std::num_get<CharT,InputIt>::do_get

С ru.cppreference.net
 
 
 
 
 
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)
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 и 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, преобразуется в числовое значение:
Ввод разбирается в соответствии с правилами std::scanf .
(до 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" ), отклонялись методом 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' разбирались

Смотрите также

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