Программирование >>  Операторы преобразования типа 

1 ... 217 218 219 [ 220 ] 221 222 223 ... 239


Стандартные фацеты соответствуют не только этим требованиям, но и некоторым специальным рекомендациям - не обязательным, но весьма полезным.

О Все функции класса объявляются константными. Это полезно, поскольку функция use facet() возвращает ссылку на константный фацет. Функции, не объявленные константными, вызываться не могут.

О Все открытые функции объявляются невиртуальными и передают запросы защищенным виртуальным функциям. Имя защищенной функции совпадает с именем открытой функции, с добавлением префикса do . Например, функция numpunct::truename() вызывает функцию numpunct::do truename(). Подобная схема выбора имен помогает избежать замещения функций при переопределении только одной из нескольких виртуальных функций с одинаковыми именами. Например, класс num put содержит несколько функций с именем put. Кроме того, программист базового класса может включить в невиртуальные функции дополнительный код, который будет выполняться даже в случае переопределения виртуальных функций.

Следующее описание стандартных фацетов относится только к открытым функциям. Чтобы изменить фацет, всегда приходится переопределять соответствующие защищенные функции. Определение функций с таким же интерфейсом, как у открытых функций фацета, всего лишь перегрузит их, поскольку эти функции не являются виртуальными.

Для большинства стандартных фацетов определяется версия с суффиксом byname. Она является производной от стандартного фацета и создает специализацию для соответствующего имени локального контекста. Так, класс numpunct byname создает фацет numpunct для локального контекста с заданным именем. Например, команда создания немецкого фацета numpunct может выглядеть так:

std::numpunct byname( de DE )

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

Числовое форматирование

средства числового форматирования преобразуют числа из внутреннего представления в соответствующее текстовое представление. Операторы потоков данных порзают работу по непосредствешому преобразованию фацетам категории locale::numeric. Эта категория состоит из трех фацетов:

О numpunct - правила оформления, используемые при форматировании и лексическом разборе чисел;

О num put - форматирование чисел при выводе;

О num get - лексический разбор чисел при вводе.

В двух словах, фацет num put выполняет операции числового форматирования, описанные для потоков данных на с. 589, а num.get - лексический разбор соответствующих строк. Фацет numpunct предоставляет дополнительные возможности, недоступные непосредственно через интерфейс потоков данных.



Оформление

Фацет numpunct определяет символ, используемый в качестве десятичной точки, управляет вставкой необязательных разделителей групп разрядов, а также задает текстовые представления логических значений. Функции фацета numpunct перечислены в табл. 14.7.

Таблица 14.7. Функции фацета numpunct

Выражение Описание

np.decimaljDOintO Возвращает символ, используемый в качестве десятичной точки

np.thousand5 sep0 Возвращает символ разделения групп разрядов

np.groupingO Возвращает объект string с описанием позиций разделителей

np.tmenameO Возвращает текстовое представление значения true

np.falsenameO Возвращает текстовое представление значения false

В аргументе шаблона numpunct передается символьный тип charT. Символы, возвращаемые функциями decimaLpoint() и thousand sep(), относятся к этому типу, а функции truename() и falsename() возвращают baslc string<charT>. Обязательна поддержка двух специализаций numpunct<char> и numpunct<wchar t>.

Поскольку числа из множества цифр плохо читаются без промежуточных разделителей, стандартные фацеты числового форматирования и лексического разбора позволяют разделять фуппы разрядов. Чаще всего цифры, представляющие целое число, группируются по триплетам. Например, в США один миллион записывается так:

1.000.000

к сожалению, такое представление используется не везде. Например, в Германии для разделения группы разрядов используется точка, поэтому немец запишет это же число в несколько ином виде:

1.000.000

Символ-разделитель определяется функцией thousands sep(). Но и этого недостаточно, поскольку в некоторых странах встречаются другие правила разделения разрядов. Например, в Непале один миллион записывается в виде:

10.00.000

в этом случае разные группы содержат разное количество цифр. В таких случаях может пригодиться строка, возвращаемая функцией grouplng(). Цифра в позиции с индексом i определяет количество разрядов в i-й группе, отсчет ведется от нуля с крайней правой группы. Если количество символов в строке меньше количества групп, размер последней заданной группы применяется повторно. Значение numericjlmlts<char>::max() определяет группу неограниченного размера, а при полном отсутствии групп используется пустая строка. В табл. 14.8 приведены примеры разного форматирования одного числа.



Таблица 14.6. Примеры разделения разрядов в одном миллионе Строка Результат

{ О } или (используется по умолчанию) 1000000

{ 3, О } или {\3} 1,000,000

{ 3, 2, 3, О } или \3\2\3 10,00,000

{ 2, CHAR MAX, О > 10000,00

Обратите внимание, что обычные цифры в данном случае практически бесполезны. Например, строка 2 для кодировки ASCII определяет группы в 50 цифр, потому что символу 2 в кодировке ASCII соответствует целочисленный код 50.

Форматирование

Фацет num put обеспечивает текстовое форматирование чисел. Он представляет собой шаблон класса с двумя аргументами: тип charT определяет символы, создаваемые при выводе, а тип Outit определяет итератор вывода для записи сгенерированных символов. По умолчанию итератор вывода относится к типу ostreambuf iterator<charT>. Фацет num put поддерживает семейство функций, которые называются put() и различаются только по последнему аргументу. Пример использования фацета num put:

std::locale loc: Dutit to = ...:

std::ios base& fmt = ...: CharT fill = ...:

T value = ...:

Получение фацета числового форматирования для контекста loc const std::num put<charT.DutIt>& np = std::use facet<std::num put<charT,OutIt> >(loc);

Вывод данных с использованием фацета np.put(to. fmt, fill, value);

Приведенный фрагмент строит текстовое представление значения value с помощью символов типа charT и выводит их через итератор вьшода to. Формат вывода определяется флагами форматирования, хранящимися в fmt, а символ fill используется в качестве заполнителя. Функция put() возвращает итератор для позиции, следующей за последним из выведенных символов.

Фацет num put содержит функции для типов bool, long, unsigned long, double, long double и void*, передаваемых в последнем аргументе, и не содержит функций для таких типов, как short или int, но это не вызывает проблем, поскольку соответствующие значения базовых типов в случае необходимости автоматически преобразуются к поддерживаемым типам.

Стандарт требует, чтобы в каждом локальном контексте хранились две специализации num put<char> и num put<wchar t> (в обеих специализациях для второго аргумента используется значение по умолчанию). Кроме того, стандарт-



1 ... 217 218 219 [ 220 ] 221 222 223 ... 239

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика