Test program: ======================================================================= #include <locale.h> #include <monetary.h> #include <stdio.h> int main () { char buf[80]; printf ("currency = |%s|\n", localeconv()->currency_symbol); printf ("positive sign = |%s|\n", localeconv()->positive_sign); printf ("negative sign = |%s|\n", localeconv()->negative_sign);
strfmon (buf, sizeof (buf), "%^#5.0n", 123.4); printf ("strfmon result for positive value = |%s|\n", buf); strfmon (buf, sizeof (buf), "%^#5.0n", -123.4); printf ("strfmon result for negative value = |%s|\n", buf); } ======================================================================= Results ======= Result on glibc 2.23: currency = || positive sign = || negative sign = || strfmon result for positive value = | 123| strfmon result for negative value = |- 123| Result on Solaris 10: currency = || positive sign = || negative sign = || strfmon result for positive value = | 123| strfmon result for negative value = |- 123| Result on Mac OS X 10.12: currency = || positive sign = || negative sign = || strfmon result for positive value = | 123 | strfmon result for negative value = |( 123)| Discussion ========== The POSIX spec is at [1]. I don't think the Mac OS X 10.12 result is correct because the test program does not specify the '+' nor '(' flag, and POSIX says If '+' is specified, the locale's equivalent of '+' and '-' are used (for example, in many locales, the empty string if positive and '-' if negative). If '(' is specified, negative amounts are enclosed within parentheses. If neither flag is specified, the '+' style is used. I don't think the glibc and Solaris results are correct because they show a '-' sign, although localeconv()->negative_sign is the empty string (which is mandated by POSIX [2]). The Solaris result is worse than the glibc one, because it produces a different number of characters in the negative and in the positive case, which is against what POSIX says for the '#' flag: To ensure alignment, any characters appearing before or after the number in the formatted output such as currency or sign symbols are padded as necessary with <space> characters to make their positive and negative formats an equal length. The result I would have expected is therefore: currency = || positive sign = || negative sign = || strfmon result for positive value = | 123| strfmon result for negative value = | 123| Conclusion ========== strfmon in the C locale is unusable. strfmon in territory locales is probably not much better. I won't spend time to add workarounds for it, because * C is a system programming language, while strfmon is for applications. Applications nowadays are not being written in C any more (except in GNOME). * Especially applications that deal with money. Given the amount of programming mistakes one can do in C and the amount of security vulnerabilities that C programs have on average (compared to other programming languages), who would want to to write monetary applications in C? Bruno [1] http://pubs.opengroup.org/onlinepubs/9699919799/functions/strfmon.html [2] http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_03_01