Although the C programming language standard in conjunction with POSIX provides a means of specifying and accessing monetary information, these standards do not define a subroutine that formats monetary quantities. The XPG strfmon subroutine provides the facilities to format monetary quantities. There is no defined subroutine that converts a formatted monetary string into a numeric quantity suitable for arithmetic. Applications that need to do arithmetic on monetary quantities may do so after processing the locale-dependent monetary string into a number. The culture-specific monetary formatting information is specified by the LC_MONETARY category. An application can obtain information pertaining to the monetary format and the currency symbol by calling the localeconv subroutine.
The strfmon subroutine uses the information from the locale's LC_MONETARY category to determine the correct monetary format for the given language/territory. With the advent of the common European currency (Euro), locales must be able to handle both the traditional national currencies as well as the common European currency. This is accomplished via the @euro modifier. Each European country that uses the Euro will have an additional LC_MONETARY definition with the @euro modifier appended. This alternate format will be invoked when specified via the locale environment variables, or with the setlocale subroutine.
To use the French locale , UTF-8 codeset environment, and French francs as the monetary unit, simply set:
LANG=FR_FR
To use the French locale, UTF-8 codeset environment,and Euros as the monetary unit, set:
LANG=FR_FR LC_MONETARY=FR_FR@euro
Users should NOT attempt to set LANG=FR_FR@euro, as the @euro variant for locale categories other than LC_MONETARY is undefined.
#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){ ... /* Error handling */ } match = sscanf(argv[1], "%f", &value); if (!match) { ... /* Error handling */ } match = sscanf(argv[2], "%s", format); if (!match) { ... /*Error handling */ } size = strfmon(bfr, 256, format, value); if (size == -1) { ... /* Error handling */ } printf ("Formatted monetary value is: %s\n", bfr); }
The following table provides examples of some of the possible conversion specifications and the outputs for 12345.67 and -12345.67 in a US English locale:
Conversion Specification | Output | Description |
---|---|---|
%n | $12,345.67 -$12,345.67 | Default formatting |
%15n | $12,345.67 -$12,345.67 | Right justifies within a 15-character field. |
%#6n | $ 12,345.67 -$ 12,345.67 | Aligns columns for values up to 999,999. |
%=*#8n | $****12,345.67 -$****12,345.67 | Specifies a fill character. |
%=0#8n | $000012,345.67 -$000012,345.67 | Fill characters do not use grouping. |
%^#6n | $ 12345.67 -$ 12345.67 | Disables the thousands separator. |
%^#6.0n | $ 12346 -$ 12346 | Rounds off to whole units. |
%^#6.3n | $ 12345.670 -$ 12345.670 | Increases the precision. |
%(#6n | $ 12,345.67 ($ 12,345.67) | Uses an alternate positive or negative style. |
%!(#6n | 12,345.67 ( 12,345.67) | Disables the currency symbol. |
char *input; /* the input multibyte string containing the monetary string */ char *output; /* the numeric string obtained from the input string */ wchar_t src_string[SIZE], dest_string[SIZE]; wchar_t *monetary, *numeric; wchar_t mon_decimal_point, radixchar; wchar_t wc; localeconv *lc; /* Initialize input and output to point to valid buffers as appropriate. */ /* Convert the input string to process code form*/ retval = mbstowcs(src_string, input, SIZE); /* Handle error returns */ monetary = src_string; numeric = dest_string; lc = localeconv(); /* obtain the LC_MONETARY and LC_NUMERIC info */ /* Convert the monetary decimal point to wide char form */ retval = mbtowc( &mon_decimal_point, lc->mon_decimal_point, MB_CUR_MAX); /* Handle any error case */ /* Convert the numeric decimal point to wide char form */ retval = mbtowc( &radixchar, lc->decimal_point, MB_CUR_MAX); /* Handle error case */ /* Assuming the string is converted first into wide character ** code form via mbstowcs, monetary points to this string. */ /* Pick up the numeric information from the wide character ** string and copy it into a temp buffer. */ while(wc = *monetary++){ if(iswdigit(wc)) *numeric++ = wc; else if( wc == mon_decimal_point) *numeric++=radixchar; } *numeric = 0; /* dest_string has the numeric value of the monetary quantity. */ /* Convert the numeric quantity into multibyte form */ retval = wcstombs( output, dest_string, SIZE); /* Handle any error returns */ /* Output contains a numeric value suitable for atof conversion. */
National Language Support Subroutines Overview provides information about wide character and multibyte subroutines.
For general information about internationalizing programs, see National Language Support Overview for Programming and Locale Overview for Programming .
The strfmon subroutine.