25 Localization library [localization]

25.4 Standard locale categories [locale.categories]

25.4.2 The numeric category [category.numeric]

Классы num_­get<> и num_­put<> обрабатывают числовое форматирование и синтаксический анализ. Виртуальные функции предусмотрены для нескольких числовых типов. Реализации могут (но не обязаны) делегировать извлечение более мелких типов экстракторам для более крупных типов.239

Все спецификации функций членов для num_­put и num_­get в подразделах[category.numeric] применяются только к специализации , требуемой в таблицах69 и70 ([locale.category]), а именно num_­get<char>, num_­get<wchar_­t>, num_­get<C, InputIterator>, num_­put<char>, num_­put<wchar_­t>, и num_­put<C, OutputIterator>. Эти специализации относятся к ios_­base& аргументу для спецификаций форматирования ([locale.categories]) и к его встроенному языку для numpunct<> фасета, чтобы идентифицировать все предпочтения числовой пунктуации, а также к ctype<> фасету для выполнения классификации символов.

Экстрактор и вставляют члены стандартного iostreams использования num_­get<> и num_­put<> функция - членов для форматирования и синтаксического анализа числовых значений ([istream.formatted.reqmts],[ostream.formatted.reqmts]).

"-1" Правильный синтаксический анализ , например, unsigned short требует, чтобы член-корреспондент get() по крайней мере извлек знак перед делегированием.

25.4.2.1 Class template num_­get [locale.num.get]

namespace std {
  template <class charT, class InputIterator = istreambuf_iterator<charT>>
    class num_get : public locale::facet {
    public:
      using char_type = charT;
      using iter_type = InputIterator;

      explicit num_get(size_t refs = 0);

      iter_type get(iter_type in, iter_type end, ios_base&,
                    ios_base::iostate& err, bool& v) const;
      iter_type get(iter_type in, iter_type end, ios_base&,
                    ios_base::iostate& err, long& v) const;
      iter_type get(iter_type in, iter_type end, ios_base&,
                    ios_base::iostate& err, long long& v) const;
      iter_type get(iter_type in, iter_type end, ios_base&,
                    ios_base::iostate& err, unsigned short& v) const;
      iter_type get(iter_type in, iter_type end, ios_base&,
                    ios_base::iostate& err, unsigned int& v) const;
      iter_type get(iter_type in, iter_type end, ios_base&,
                    ios_base::iostate& err, unsigned long& v) const;
      iter_type get(iter_type in, iter_type end, ios_base&,
                    ios_base::iostate& err, unsigned long long& v) const;
      iter_type get(iter_type in, iter_type end, ios_base&,
                    ios_base::iostate& err, float& v) const;
      iter_type get(iter_type in, iter_type end, ios_base&,
                    ios_base::iostate& err, double& v) const;
      iter_type get(iter_type in, iter_type end, ios_base&,
                    ios_base::iostate& err, long double& v) const;
      iter_type get(iter_type in, iter_type end, ios_base&,
                    ios_base::iostate& err, void*& v) const;

      static locale::id id;

    protected:
      ~num_get();
      virtual iter_type do_get(iter_type, iter_type, ios_base&,
                               ios_base::iostate& err, bool& v) const;
      virtual iter_type do_get(iter_type, iter_type, ios_base&,
                               ios_base::iostate& err, long& v) const;
      virtual iter_type do_get(iter_type, iter_type, ios_base&,
                               ios_base::iostate& err, long long& v) const;
      virtual iter_type do_get(iter_type, iter_type, ios_base&,
                               ios_base::iostate& err, unsigned short& v) const;
      virtual iter_type do_get(iter_type, iter_type, ios_base&,
                               ios_base::iostate& err, unsigned int& v) const;
      virtual iter_type do_get(iter_type, iter_type, ios_base&,
                               ios_base::iostate& err, unsigned long& v) const;
      virtual iter_type do_get(iter_type, iter_type, ios_base&,
                               ios_base::iostate& err, unsigned long long& v) const;
      virtual iter_type do_get(iter_type, iter_type, ios_base&,
                               ios_base::iostate& err, float& v) const;
      virtual iter_type do_get(iter_type, iter_type, ios_base&,
                               ios_base::iostate& err, double& v) const;
      virtual iter_type do_get(iter_type, iter_type, ios_base&,
                               ios_base::iostate& err, long double& v) const;
      virtual iter_type do_get(iter_type, iter_type, ios_base&,
                               ios_base::iostate& err, void*& v) const;
    };
}

Фасет num_­get используется для синтаксического анализа числовых значений из входной последовательности, такой как istream.

25.4.2.1.1 num_­get members [facet.num.get.members]

iter_type get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, bool& val) const; iter_type get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, long& val) const; iter_type get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, long long& val) const; iter_type get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, unsigned short& val) const; iter_type get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, unsigned int& val) const; iter_type get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, unsigned long& val) const; iter_type get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, unsigned long long& val) const; iter_type get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, float& val) const; iter_type get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, double& val) const; iter_type get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, long double& val) const; iter_type get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, void*& val) const;

Returns: do_­get(in, end, str, err, val).

25.4.2.1.2 num_­get virtual functions [facet.num.get.virtuals]

iter_type do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, long& val) const; iter_type do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, long long& val) const; iter_type do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, unsigned short& val) const; iter_type do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, unsigned int& val) const; iter_type do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, unsigned long& val) const; iter_type do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, unsigned long long& val) const; iter_type do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, float& val) const; iter_type do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, double& val) const; iter_type do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, long double& val) const; iter_type do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, void*& val) const;

Effects: Читает символыin, интерпретируя их в соответствии с str.flags(), use_­facet<ctype<​charT>>(loc)и use_­facet<numpunct<charT>>(loc), где loc это str.getloc().

Детали этой операции происходят в три этапа.

  • Этап 1. Определение спецификатора преобразования

  • Этап 2: извлечение символовin и определение соответствующего char значения для формата, ожидаемого спецификацией преобразования, определенной на этапе 1.

  • Этап 3: сохранение результатов

Подробности этапов представлены ниже.

  • Этап 1: функция инициализирует локальные переменные через

    fmtflags flags = str.flags();
    fmtflags basefield = (flags & ios_base::basefield);
    fmtflags uppercase = (flags & ios_base::uppercase);
    fmtflags boolalpha = (flags & ios_base::boolalpha);

    Для преобразования в целочисленный тип функция определяет спецификатор целочисленного преобразования, как указано в таблице73. Стол заказан. То есть применяется первая строка, для которой выполнено условие.

    Таблица73 - Целочисленные преобразования
    Состояниеstdio эквивалент
    basefield == oct %o
    basefield == hex %X
    basefield == 0 %i
    signed интегральный тип %d
    unsigned интегральный тип %u

    Для преобразований в плавающий тип спецификатором является %g.

    Для преобразований void* в спецификатор есть %p.

    При необходимости в спецификацию преобразования добавляется модификатор длины, как указано в таблице74.

    Таблица74 - модификатор длины
    Тип Модификатор длины
    short h
    unsigned short h
    long l
    unsigned long l
    long long ll
    unsigned long long ll
    double l
    long double L
  • Этап 2: Если in == end затем этап 2 завершается. В противном случае a charT берется из,in и локальные переменные инициализируются, как если бы

    char_type ct = *in;
    char c = src[find(atoms, atoms + sizeof(src) - 1, ct) - atoms];
    if (ct == use_facet<numpunct<charT>>(loc).decimal_point())
    c = '.';
    bool discard =
      ct == use_facet<numpunct<charT>>(loc).thousands_sep()
      && use_facet<numpunct<charT>>(loc).grouping().length() != 0;

    где значения src и atoms определяются как если бы:

    static const char src[] = "0123456789abcdefxABCDEFX+-";
    char_type atoms[sizeof(src)];
    use_facet<ctype<charT>>(loc).widen(src, src + sizeof(src), atoms);

    для этого значения loc.

    Еслиdiscard естьtrue, то, если '.' он еще не накоплен, запоминается позиция символа, но в противном случае символ игнорируется. В противном случае, если '.' он уже накоплен, символ сбрасывается, и этап 2 завершается. Если он не отбрасывается, то выполняется проверка, чтобы определить,c разрешен ли он в качестве следующего символа поля ввода спецификатора преобразования, возвращаемого на этапе 1. Если да, то он накапливается.

    Если символ либо отбрасывается, либо накапливается, онin продвигается вперед, ++in и обработка возвращается к началу этапа 2.

  • Этап 3: последовательностьchars, накопленная на этапе 2 (поле), преобразуется в числовое значение по правилам одной из функций, объявленных в заголовке<cstdlib>:

    • Для целого числа со знаком функцияstrtoll.

    • Для целочисленного значения без знака функцияstrtoull.

    • Дляfloat значения функцияstrtof.

    • Дляdouble значения функцияstrtod.

    • Дляlong double значения функцияstrtold.

    Сохраняемое числовое значение может быть одним из:

    • ноль, если функция преобразования не преобразовывает все поле.

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

    • наиболее положительное представимое значение, если поле, которое нужно преобразовать в беззнаковый целочисленный тип, представляет значение, которое не может быть представлено вval.

    • преобразованное значение, в противном случае.

    Результирующее числовое значение сохраняется вval. Если функция преобразования не преобразует все поле или если поле представляет значение вне диапазона представимых значений, ios_­base​::​failbit присваиваетсяerr.

Группировка цифр проверяется. Таким образом, позиции отброшенных разделителей проверяются на соответствие use_­facet<numpunct<charT>>(loc).grouping(). Если они не согласуются, то ios_­base​::​failbit назначаетсяerr.

В любом случае, если обработка этапа 2 была прервана тестом, in == end то err |= ios_­base​::​eofbit выполняется.

iter_type do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, bool& val) const;

Effects: Если (str.flags()&ios_­base​::​boolalpha) == 0 затем ввод происходит так же, как и для a, long за исключением того, что если значение сохраняетсяval, значение определяется в соответствии со следующим: Если значение, которое должно быть сохранено, равно 0, то false оно сохраняется. Если значение,1 то true сохраняется. В противном случаеtrue сохраняется иios_­base​::​failbit присваиваетсяerr.

В противном случае целевые последовательности определяются «как если бы» путем вызова членов falsename() и truename() фасета, полученного с помощью use_­facet<numpunct<charT>>(str.getloc()). Последовательные символы в диапазоне [in, end) (см.[sequence.reqmts]) Получаются и сопоставляются с соответствующими позициями в целевых последовательностях только по мере необходимости для идентификации уникального совпадения. Итератор вводаin сравниваетсяend только тогда, когда это необходимо для получения символа. Если целевая последовательность однозначно соответствует,val устанавливается соответствующее значение. В противном случаеfalse сохраняется иios_­base​::​failbit присваиваетсяerr.

in Итератор всегда остается указывая на одну позицию за пределы последнего символа, соответствующего образцу . Еслиval установлено, тоerr устанавливается в str.goodbit; или str.eofbit если при поиске другого символа для сопоставления обнаруживается, что (in == end). Еслиval не установлен, тоerr устанавливается в str.failbit; или (str.failbit|str.eofbit) если причина отказа была в этом (in == end). [ Example: Для целей true: "a" и false: "abb"входная последовательность "a" дает val == true и err == str.eofbit; входная последовательность "abc" дает результат err = str.failbitсin окончанием на 'c' элементе. Для целей true: "1" и false: "0"входная последовательность"1" дает val == true и err == str.goodbit. Для пустых целей("")любая входная последовательность дает результат err == str.failbit. ]end example

Returns: in.

25.4.2.2 Class template num_­put [locale.nm.put]

namespace std {
  template <class charT, class OutputIterator = ostreambuf_iterator<charT>>
    class num_put : public locale::facet {
    public:
      using char_type = charT;
      using iter_type = OutputIterator;

      explicit num_put(size_t refs = 0);

      iter_type put(iter_type s, ios_base& f, char_type fill, bool v) const;
      iter_type put(iter_type s, ios_base& f, char_type fill, long v) const;
      iter_type put(iter_type s, ios_base& f, char_type fill, long long v) const;
      iter_type put(iter_type s, ios_base& f, char_type fill, unsigned long v) const;
      iter_type put(iter_type s, ios_base& f, char_type fill, unsigned long long v) const;
      iter_type put(iter_type s, ios_base& f, char_type fill, double v) const;
      iter_type put(iter_type s, ios_base& f, char_type fill, long double v) const;
      iter_type put(iter_type s, ios_base& f, char_type fill, const void* v) const;

      static locale::id id;

    protected:
      ~num_put();
      virtual iter_type do_put(iter_type, ios_base&, char_type fill, bool v) const;
      virtual iter_type do_put(iter_type, ios_base&, char_type fill, long v) const;
      virtual iter_type do_put(iter_type, ios_base&, char_type fill, long long v) const;
      virtual iter_type do_put(iter_type, ios_base&, char_type fill, unsigned long) const;
      virtual iter_type do_put(iter_type, ios_base&, char_type fill, unsigned long long) const;
      virtual iter_type do_put(iter_type, ios_base&, char_type fill, double v) const;
      virtual iter_type do_put(iter_type, ios_base&, char_type fill, long double v) const;
      virtual iter_type do_put(iter_type, ios_base&, char_type fill, const void* v) const;
    };
}

Фасет num_­put используется для форматирования числовых значений в последовательность символов, такую ​​как поток.

25.4.2.2.1 num_­put members [facet.num.put.members]

iter_type put(iter_type out, ios_base& str, char_type fill, bool val) const; iter_type put(iter_type out, ios_base& str, char_type fill, long val) const; iter_type put(iter_type out, ios_base& str, char_type fill, long long val) const; iter_type put(iter_type out, ios_base& str, char_type fill, unsigned long val) const; iter_type put(iter_type out, ios_base& str, char_type fill, unsigned long long val) const; iter_type put(iter_type out, ios_base& str, char_type fill, double val) const; iter_type put(iter_type out, ios_base& str, char_type fill, long double val) const; iter_type put(iter_type out, ios_base& str, char_type fill, const void* val) const;

Returns: do_­put(out, str, fill, val).

25.4.2.2.2 num_­put virtual functions [facet.num.put.virtuals]

iter_type do_put(iter_type out, ios_base& str, char_type fill, long val) const; iter_type do_put(iter_type out, ios_base& str, char_type fill, long long val) const; iter_type do_put(iter_type out, ios_base& str, char_type fill, unsigned long val) const; iter_type do_put(iter_type out, ios_base& str, char_type fill, unsigned long long val) const; iter_type do_put(iter_type out, ios_base& str, char_type fill, double val) const; iter_type do_put(iter_type out, ios_base& str, char_type fill, long double val) const; iter_type do_put(iter_type out, ios_base& str, char_type fill, const void* val) const;

Effects: Записывает символы в последовательностьout, форматируяval по желанию. В следующем описании локальная переменная инициализируется с помощью:

locale loc = str.getloc();

Детали этой операции происходят в несколько этапов:

  • Этап 1. Определите спецификатор преобразования printfspec и определите символы, которые будут напечатаны с помощью printf ([c.files]) с учетом этого спецификатора преобразования для

    printf(spec, val)

    предполагая, что текущая локаль является"C" локалью.

  • Этап 2: Настройте представление путем преобразования каждого, char определенного на этапе 1, в a, charT используя преобразование и значения, возвращаемые членами use_­facet<numpunct<charT>>(str.getloc())

  • Этап 3: Определите, где требуется заполнение.

  • Этап 4: Вставьте последовательность в файлout.

Далее следуют подробные описания каждого этапа.

Returns: out.

  • Этап 1. Первое действие этапа 1 - определить спецификатор преобразования. В таблицах, описывающих это определение, используются следующие локальные переменные

    fmtflags flags = str.flags();
    fmtflags basefield =  (flags & (ios_base::basefield));
    fmtflags uppercase =  (flags & (ios_base::uppercase));
    fmtflags floatfield = (flags & (ios_base::floatfield));
    fmtflags showpos =    (flags & (ios_base::showpos));
    fmtflags showbase =   (flags & (ios_base::showbase));
    fmtflags showpoint =  (flags & (ios_base::showpoint));

    Все таблицы, используемые при описании этапа 1, заказаны. То есть применяется первая строка, для которой выполнено условие. Строка без условия является поведением по умолчанию, когда ни одна из предыдущих строк не применяется.

    Для преобразования из целочисленного типа, отличного от символьного, функция определяет спецификатор целочисленного преобразования, как указано в таблице75.

    Таблица75 - Целочисленные преобразования
    Состояниеstdio эквивалент
    basefield == ios_­base​::​oct %o
    (basefield == ios_­base​::​hex) && !uppercase %x
    (basefield == ios_­base​::​hex) %X
    дляsigned целого типа %d
    дляunsigned целого типа %u

    Для преобразования из типа с плавающей запятой функция определяет спецификатор преобразования с плавающей запятой, как указано в таблице76.

    Таблица76 - Преобразования с плавающей запятой
    Состояниеstdio эквивалент
    floatfield == ios_­base​::​fixed %f
    floatfield == ios_­base​::​scientific && !uppercase %e
    floatfield == ios_­base​::​scientific %E
    floatfield == (ios_­base​::​fixed | ios_­base​::​scientific) && !uppercase %a
    floatfield == (ios_­base​::​fixed | ios_­base​::​scientific) %A
    !uppercase %g
    otherwise %G

    Для преобразований из целочисленного типа или типа с плавающей запятой к спецификатору преобразования добавляется модификатор длины, как указано в таблице77.

    Таблица77 - модификатор длины
    Тип Модификатор длины
    long l
    long long ll
    unsigned long l
    unsigned long long ll
    long double L
    otherwise none

    К спецификатору преобразования добавлены следующие необязательные дополнительные квалификаторы, как указано в таблице78.

    Таблица78 - Числовые преобразования
    Тип (ы)Состояниеstdio эквивалент
    интегральный тип showpos +
    showbase #
    тип с плавающей запятой showpos +
    showpoint #

    Для преобразования из типа с плавающей точкой, еслиfloatfield != (ios_­base​::​fixed | ios_­base​::​​scientific), str.precision() определяются как точность в спецификации преобразования. В противном случае точность не указана.

    Для преобразования из void* спецификатора есть %p.

    Представления в конце этапа 1 состоят из char's, которые будут напечатаны вызовом printf(s, val) wheres - спецификатор преобразования, определенный выше.

  • Этап 2: Любой символ,c кроме десятичной точки (.), Преобразуется в переходное charT отверстие. use_­facet<ctype<charT>>(loc).widen( c )

    Локальная переменнаяpunct инициализируется через

    const numpunct<charT>& punct = use_facet<numpunct<charT>>(str.getloc());

    Для арифметических типов punct.thousands_­sep() символы вставляются в последовательность, как определено значением, возвращаемым с punct.do_­grouping() помощью метода, описанного в[facet.numpunct.virtuals]

    Символы десятичной точки (.) Заменяются на punct.decimal_­point()

  • Этап 3: локальная переменная инициализируется как

    fmtflags adjustfield = (flags & (ios_base::adjustfield));

    Расположение любой прокладки240 определяется по Табл79.

    Таблица79 - заполнение заполнения
    СостояниеМесто нахождения
    adjustfield == ios_­base​::​left подушечка после
    adjustfield == ios_­base​::​right колодка перед
    adjustfield == internal и знак встречается в представлении блокнот после знака
    adjustfield == internal и представление после этапа 1 началось с 0x или 0X проложить после x или X
    otherwise колодка перед

    Если не str.width() равно нулю и количество символовcharTв последовательности после этапа 2 меньше чем str.​width(), тоfill в последовательность добавляется достаточное количество символов в позиции, указанной для заполнения, чтобы довести длину последовательности до str.width().

    str.width(0) называется.

  • Этап 4: последовательность charTсимволов в конце этапа 3 выводится через

    *out++ = c

iter_type do_put(iter_type out, ios_base& str, char_type fill, bool val) const;

Returns: Если (str.flags() & ios_­base​::​boolalpha) == 0 возвращается do_­put(out, str, fill,
(int)val)
, иначе получает строку, s как если бы

string_type s =
  val ? use_facet<numpunct<charT>>(loc).truename()
      : use_facet<numpunct<charT>>(loc).falsename();

а затем вставляет каждый символ c в s переходное out отверстие *out++ = c и возвращает out.

Спецификация преобразования #o генерирует интерлиньяж, 0 который является not символом заполнения.