Классы 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() по крайней мере извлек знак перед делегированием.
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.
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;
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: функция инициализирует локальные переменные через
fmtflags flags = str.flags(); fmtflags basefield = (flags & ios_base::basefield); fmtflags uppercase = (flags & ios_base::uppercase); fmtflags boolalpha = (flags & ios_base::boolalpha);
Для преобразования в целочисленный тип функция определяет спецификатор целочисленного преобразования, как указано в таблице73. Стол заказан. То есть применяется первая строка, для которой выполнено условие.
Состояние | stdio эквивалент |
basefield == oct | %o |
basefield == hex | %X |
basefield == 0 | %i |
signed интегральный тип | %d |
unsigned интегральный тип | %u |
Для преобразований в плавающий тип спецификатором является %g.
Для преобразований void* в спецификатор есть %p.
При необходимости в спецификацию преобразования добавляется модификатор длины, как указано в таблице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
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 используется для форматирования числовых значений в последовательность символов, такую как поток.
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;
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.
Этап 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.
Состояние | stdio эквивалент |
basefield == ios_base::oct | %o |
(basefield == ios_base::hex) && !uppercase | %x |
(basefield == ios_base::hex) | %X |
дляsigned целого типа | %d |
дляunsigned целого типа | %u |
Для преобразования из типа с плавающей запятой функция определяет спецификатор преобразования с плавающей запятой, как указано в таблице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.
Тип | Модификатор длины |
long | l |
long long | ll |
unsigned long | l |
unsigned long long | ll |
long double | L |
otherwise | none |
К спецификатору преобразования добавлены следующие необязательные дополнительные квалификаторы, как указано в таблице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.
Состояние | Место нахождения |
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 символом заполнения.