Options for the strfmon() Function

The strfmon() function, introduced in last week’s Lesson properly formats a monetary value for specific regions. To unlock the function’s various features, you must understand and use formatting placeholders.

The placeholders used in the strfmon() function operate like placeholders used by printf() and scanf(), though different placeholders are used. Like the printf() function’s placeholders, the strfmon() placeholders are prefixed by the % character, which can be followed by optional characters to set specifics, then a final character to define the placeholder.

The two common, and most reliable, placeholders are %n and %i. These set the output for the national and international currencies, respectively:

2021_03_27-Lesson-a.c

#include <stdio.h>
#include <locale.h>
#include <monetary.h>

int main()
{
    char buffer[32];
    char *r;

    r = setlocale(LC_ALL,"en_US.UTF-8");
    if( r==NULL )
    {
        fprintf(stderr,"Unable to set locale\n");
        return(1);
    }

    strfmon(buffer,32,"International format: %i",359246.80);
    puts(buffer);
    strfmon(buffer,32,"National format: %n",359246.80);
    puts(buffer);

    return(0);
}

Here is the output:

International format: USD 359,246.80
National format: $359,246.80

As an aside, under OS X the International format was output as USD359,24z???, which is some kinda formatting bug on the Mac. If you’re using a Mac, be aware that the strfmon() function may not be properly implemented.

In fact, be aware that this function may not be properly implemented on any platform. This reason may be why the function isn’t included with the MinGW compiler or why it’s relatively unknown.

To explore the conversion character options, I concocted a test program. Like my series on printf() conversion characters (placeholders), I figured a program that runs through all the options and variations would be keen, both to present how the options are used and their effect on output.

Here’s how far I got:

2021_03_27-Lesson-b.c

#include <stdio.h>
#include <locale.h>
#include <monetary.h>

int main()
{
    char buffer[32];
    char *r;

    r = setlocale(LC_ALL,"en_US.UTF-8");
    if( r==NULL )
    {
        fprintf(stderr,"Unable to set locale\n");
        return(1);
    }

    strfmon(buffer,32,"Normal: %n",359246.80);
    puts(buffer);
    strfmon(buffer,32,"No grouping characters: %^n",359246.80);
    puts(buffer);
    strfmon(buffer,32,"No currency symbol: %!n",359246.80);
    puts(buffer);
    strfmon(buffer,32,"Left justification: %-30n",359246.80);
    puts(buffer);

    return(0);
}

The three placeholder options I explored are:

Line 19, The ^ character that suppresses the hundreds/thousands separator.

Line 21, the ! character that suppresses the currency symbol.

Line 23, The -30 option that should set output width to 30 characters, left-justified.

Here is the output generated on the Macintosh:

Normal: $359,246.80
No grouping characters: $359246:??
No currency symbol: 359,246.80
Left justification: 359,246.80

And for Ubuntu Linux:

Normal: $359,246.80
No grouping characters: $359246:?
No currency symbol: 359,246.80
Left justification: 359,246.80

Both systems failed on the ^ no-grouping test, throwing garbage into the string. The left justification item failed as well. While it could be argued that I didn’t properly use the formatting strings, this output was enough to make me distrust the function to the degree that I’d never use it.

The premise for the strfmon() function is interesting and possibly could have value specifically for code you write that’s run in a variety of countries or regions. Alas, the placeholder documentation on the web is weak and confusing. The best documentation I found is from IBM:

https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_74/rtref/strfmon.htm

As long as international conversion isn’t required for your code, my advice is to craft your own monetary output function. A very early Exercise post on this blog offers some assistance in formatting output values with hundreds/thousands separators. The rest is up to you.

Leave a Reply