Несмотря на то, что в стандартах языка C, поддерживающих POSIX, существуют средства работы с информацией о денежных суммах, в состав этих средств не входят функции преобразования их формата. Такая возможность предоставляется функцией XPG strfmon. Функций, преобразующих строки в формате денежных сумм в числовой формат, который допускает выполнение арифметических операций, не существует. Для выполнения такой операции в приложении можно преобразовать строку денежной суммы, заданную в соответствии с параметрами текущей локали, в число. Информация о формате национальных денежных единиц хранится в категории LC_MONETARY. Для передачи приложению информации о формате денежных сумм и символа национальной валюты служит функция localeconv.
Для определения формата представления денежных сумм в соответствии с национальными стандартами функция strfmon использует информацию из категории локали LC_MONETARY. С введением общеевропейской валюты Евро возникла потребность поддержки не только традиционных национальных валют, но и Евро. Для этой цели был веден модификатор @euro. В локаль каждого европейского государства, в котором имеет хождение Евро, добавлено определение LC_MONETARY с модификатором @euro. Этот альтернативный формат применяется, если он указан в переменной среды локали, а также в функции setlocale.
Для работы с французской локалью, кодовым набором UTF-8 и французским франком в качестве денежной единицы следует указать:
LANG=FR_FR
Для работы с французской локалью, кодовым набором UTF-8 и Евро в качестве денежной единицы следует указать:
LANG=FR_FR LC_MONETARY=FR_FR@euro
Не следует указывать LANG=FR_FR@euro, так как значение @euro для любой категории локали, отличной от LC_MONETARY, не определено.
#include <monetary.h>
#include <locale.h>
#include <stdio.h>
main(int argc, char **argv)
{
char bfr[256], format[256];
int match; ssize_t size;
float value;
(void) setlocal(LC_ALL, "");
if (argc != 3){
... /* Обработка ошибок */
}
match = sscanf(argv[1], "%f", &value);
if (!match) {
... /* Обработка ошибок */
}
match = sscanf(argv[2], "%s", format);
if (!match) {
... /* Обработка ошибок */
}
size = strfmon(bfr, 256, format, value);
if (size == -1) {
... /* Обработка ошибок */
}
printf ("Значение денежной суммы: %s\n", bfr);
}
В следующей таблице приведены примеры возможных спецификаций преобразования
и вывод для значений 12345.67 и -12345.67 при использовании
локали английского языка для США:
| Спецификация преобразования | Вывод | Описание |
|---|---|---|
| %n | $12,345.67 -$12,345.67 | Форматирование по умолчанию |
| %15n | $12,345.67 -$12,345.67 | Выравнивание по правому краю в поле из 15 позиций |
| %#6n | $ 12,345.67 -$ 12,345.67 | Выравнивание колонки для значений до 999,999. |
| %=*#8n | $****12,345.67 -$****12,345.67 | Применение символа заполнения. |
| %=0#8n | $000012,345.67 -$000012,345.67 | Применение символов заполнения без группировки. |
| %^#6n | $ 12345.67 -$ 12345.67 | Отмена разделителя разрядов. |
| %^#6.0n | $ 12346 -$ 12346 | Округление до целого числа. |
| %^#6.3n | $ 12345.670 -$ 12345.670 | Увеличение точности. |
| %(#6n | $ 12,345.67 ($ 12,345.67) | Изменение способа обозначения отрицательных чисел. |
| %!(#6n | 12,345.67 ( 12,345.67) | Отмена символа денежной единицы. |
char *input; /* многобайтовая входная строка, содержащая денежную сумму */
char *output; /* числовая строка, получаемая из строки ввода */
wchar_t src_string[SIZE], dest_string[SIZE];
wchar_t *monetary, *numeric;
wchar_t mon_decimal_point, radixchar;
wchar_t wc;
localeconv *lc;
/* Инициализировать input и output. */
/* Преобразовать входную строку */
retval = mbstowcs(src_string, input, SIZE);
/* Обработать возврат по ошибке */
monetary = src_string;
numeric = dest_string;
lc = localeconv();
/* получить информацию LC_MONETARY и LC_NUMERIC */
/* Преобразовать десятичное значение денежной суммы в формат широких символов */
retval = mbtowc( &mon_decimal_point, lc->mon_decimal_point,
MB_CUR_MAX);
/* Обработка ошибок */
/* Преобразовать числовое десятичное значение в формат широких символов */
retval = mbtowc( &radixchar, lc->decimal_point, MB_CUR_MAX);
/* Обрабатывать возможную ошибку */
/* monetary указывает на строку, предварительно преобразованную в формат
** широких символов с помощью mbstowcs.
*/
/* Получить числовую информацию из строки широких символов
** и скопировать во временный буфер.
*/
while(wc = *monetary++){
if(iswdigit(wc))
*numeric++ = wc;
else if( wc == mon_decimal_point)
*numeric++=radixchar;
}
*numeric = 0;
/* dest_string получает числовое значение денежной величины. */
/* Преобразовать числовую величину в многобайтовый формат */
retval = wcstombs( output, dest_string, SIZE);
/* Обработать все возвраты по ошибке */
/* Вывод содержит числовое значение, пригодное для преобразования atof */
В разделе Функции для поддержки национальных языков - Обзор приведены дополнительные сведения о функциях обработки широких и многобайтовых символов.
Общие сведения о локализации программ приведены в разделах Поддержка национальных языков в программировании - Введение (Глава 16, Поддержка национальных языков) и Локаль - Информация для программистов.
Функция strfmon.