Шаг 543.
Библиотека STL.
Интернационализация. Форматирование денежных величин. Оформление

    На этом шаге мы рассмотрим различные способы вывода значений денежных величин.

    В категорию monetary входят фацеты moneypunct, money_get и money_put. Фацет moneypunct определяет формат денежных величин, а два других фацета используют эту информацию для их форматирования или лексического разбора.

Оформление

    Вид выводимых денежных величин определяется локальным контекстом. Форматы, используемые в разных культурных сообществах, очень отличаются друг от друга. В частности, различаются обозначения денежных единиц (которые могут вообще отсутствовать), способы записи отрицательных и положительных сумм, режимы использования национального или международного обозначения денежной единицы, разделители групп разрядов и т. д. Чтобы обеспечить необходимую гибкость, атрибуты формата были выделены в фацет moneypunct.

    Фацет moneypunct представляет собой шаблон с двумя аргументами: типом charT и логическим признаком, по умолчанию равным false. Логический признак показывает, должно ли использоваться национальное (false) или международное (true) обозначение денежной единицы. Функции фацета moneypunct перечислены в таблице 1.

Таблица 1. Функции фацета moneypunct
Выражение Описание
mp.decimal_point() Возвращает символ, используемый в качестве десятичной точки
mp.thousand_sep() Возвращает символ, используемый для разделения групп разрядов
mp.grouping() Возвращает строку, определяющую размеры групп разрядов
mp.curr_symbol() Возвращает строку с обозначением денежной единицы
mp.positive_sign() Возвращает строку с обозначением знака положительного числа
mp.negative_sign() Возвращает строку с обозначением знака отрицательного числа
mp.frac_digits() Возвращает количество цифр в дробной части
mp.pos_format() Возвращает формат неотрицательных значений
mp.neg_format() Возвращает формат отрицательных значений

    Класс moneypunct объявлен производным от класса money_base. В этом базовом классе определен перечисляемый тип part, представляющий компоненты шаблона форматирования денежных величин. Кроме того, в нем определен тип pattern (синоним для char[4]). Четыре значения типа part, хранящихся в этом типе, определяют структуру денежной величины. В таблице 2 перечислены пять допустимых значений типа part, которые могут использоваться в значениях типа pattern.

Таблица 2. Компоненты шаблонов форматирования денежных величин
Значение Описание
nоnе В данной позиции могут находиться необязательные пробелы
space В данной позиции обязателен хотя бы один пробел
sign В данной позиции может находиться знак
symbol В данной позиции может находиться обозначение денежной единицы
value В данной позиции выводится значение

    В фацете moneypunct определены две функции, возвращающие шаблоны форматирования: neg_format() для отрицательных значений и pos_format() для неотрицательных значений. Шаблон форматирования содержит обязательные компоненты sign, symbol и value и один из двух компонентов nоnе или space. Впрочем, это не означает, что в итоге действительно будет выведен знак или символ денежной единицы. Содержимое соответствующих позиций зависит от значений, возвращаемых другими функциями фацета, и от форматных флагов, передаваемых функциям форматирования.

    В денежной величине заведомо присутствует только значение. Естественно, оно находится в позиции, обозначенной компонентом value шаблона форматирования. Значение содержит точно frac_digits() цифр в дробной части, а в качестве десятичной точки используется символ decimal_point() (если дробная часть отсутствует, десятичная точка ие ставится).

    При вводе денежных величин во входных данных могут присутствовать разделители групп разрядов. Если разделители присутствуют, правильность их расположения проверяется при помощи функции grouping(). Если функция grouping() возвращает пустую строку, присутствие разделителей групп недопустимо. Группы разрядов разделяются символом, возвращаемым функцией thousands_sep(). Группировка производится по тем же правилам, как при числовом форматировании (смотри 537 шаг). При выводе денежных величин разделители групп разрядов всегда вставляются в соответствии со строкой, возвращаемой функцией grouping(). При чтении денежных величин разделители групп не обязательны, если строка группировки не является пустой. Правильность расположения разделителей проверяется после успешного завершения разбора.

    Компоненты space и nоnе управляют расположением пробелов. Компонент space используется в позиции, в которой должен присутствовать по крайней мере один пробел. В процессе форматирования, если в форматных флагах установлен флаг ios_base::Internal, в позиции компонента space или nоnе вставляются символы-заполнители. Конечно, заполнение производится только в том случае, если заданная минимальная ширина не заполнена другими символами. Символ-заполнитель передается в аргументе функций форматирования денежных величин. Если отформатированное значение не содержит пробелов, nоnе может находиться в последней позиции шаблона форматирования. Компоненты space и nоnе не могут находиться в первой позиции шаблона форматирования, a space не может находиться в последней позиции.

    Знак денежной величины (положительный/отрицательный) может представляться несколькими символами. Например, в некоторых контекстах отрицательные суммы заключаются в круглые скобки. В позиции компонента sign в шаблоне форматирования выводится первый символ представления знака, остальные символы выводятся в конце после всех остальных компонентов. Если представление знака равно пустой строке, знак не отображается. Символьное представление знака определяется функцией positive_sign() для неотрицательных величин и функцией negative_sign() для отрицательных.

    В позиции компонента symbol отображается символ денежной единицы. Оно присутствует только в том случае, если среди форматных флагов, используемых при выводе или разборе, установлен флаг ios_base::showbase. В качестве представления денежного знака используется строка, возвращаемая функцией curr_symbol(). Если второй аргумент шаблона равен false (по умолчанию), то задействуется национальное обозначение денежной единицы; иначе - международное обозначение.

    В таблице 3 приведены примеры форматирования суммы $-1234.56. Конечно, предполагается, что frac_digits() возвращает 2. Кроме того, во всех случаях используется нулевая ширина поля.

Таблица 3. Примеры использования шаблонов форматирования
Шаблон форматирования Знак  
symbol none sign value   $1234.56
symbol none sign value - $-1234.56
symbol space sign value - $-1234.56
symbol space sign value () $(1234.56)
sign symbol space value () ($ 1234.56)
sign value space symbol () (1234.56 $)
symbol space value sign - $ 1234.56-
sign value space symbol - -1234.56 $
sign value none symbol - -1234.56$

    Стандарт требует, чтобы в каждом локальном контексте хранились специализации moneypunct<char>, moneypunct<wchar_t>, moneypunct<char,true> и moneypunct <wchar_t,true>. Стандартная библиотека C++ не поддерживает другие специализации.

    На следующем шаге мы рассмотрим форматирование денежных величин.




Предыдущий шаг Содержание Следующий шаг