Spec-Zone.ru › C++

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;
(с 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, 
                          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;
(с 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;
(с 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;
1) Общедоступный член-функция, вызывает член-функцию do_get самого производного класса.
2) Считывает символы из итератора ввода 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. В противном случае 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)
  • Если функция преобразования не смогла преобразовать все поле, в v сохраняется значение ​0​.
  • Если тип 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, поскольку на втором этапе фильтровались символы 'X' и 'x'.

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

class="t-rev-begin">

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

Строки, представляющие бесконечность или не число (например, "NaN" и "inf"), отклонялись do_get(double) даже если они являются допустимым вводом для strtod, поскольку на втором этапе фильтровались символы, такие как '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/w/cpp/locale/num_get/get

Spec-Zone.ru

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