Exploring the strfmon() Function

The C programming language doesn’t sport the thousands of functions (or methods or what-have-you) available in Java. They say Java programmers may never use or even know the variety. With many fewer functions available in the standard C library, I would think to know them all. Then along comes another one I’ve neither used nor heard of. This week’s Lesson covers such as function, strfmon().

If you’re familiar with C library naming conventions, you might figure out strfmon(): The str implies string. The f generally means formatted. The mon could be monitor, though here it stands for monetary: strfmon() is the string format for monetary values function.

Yes, I’ve never heard of it.

The strfmon() function takes a floating point value and applies a monetary format to it. The function works similar to the printf() function regarding the formatting process, though syntactically it’s more akin to the snprintf() function. Here is the man page format:

ssize_t strfmon(char *s, size_t max, const char *format, ...);

Buffer s is a char array or buffer of size max. It holds the string the function generates.

The format argument works similar to the printf() format string, though with unique conversion characters that apply to monetary values.

The ... argument represents the values to express in monetary format.

The strfmon() function requires that you include the monetary.h header file in your code. This function is the only function declared the header file. Not all C libraries may implement this function or have available the monetary.h header file. My Code::Blocks MinGW installation does not.

Most importantly, the strfmon() function relies heavily upon the computer’s locale data to properly format the monetary value. Without asserting the locale, the function’s output is unimpressive, as the following code demonstrates:

2021_03_20-Lesson-a.c

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

int main()
{
    char buffer[32];

    strfmon(buffer,32,"%n",359246.80);
    puts(buffer);

    return(0);
}

The strfmon() function at Line 8 has four arguments: buffer, the 32-character storage location for the string; 32, the buffer’s size; "%n" which formats the string using the locale’s national format; and the value to convert.

Here is the disappointing output:

359246.80

This example doesn’t shine because the code doesn’t know the locale. Maybe it works with some compilers, but not on the systems where I ran the test code. No, you must assert the locale before calling the function, as is done in this update:

2021_03_20-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,"%n",359246.80);
    puts(buffer);

    return(0);
}

At Line 10, the setlocale() function is called with the locale to en_US.UTF-8, or American English. Like all good code, Line 11 tests for any errors and exits the program if one is encountered.

Upon building this updated code, the output is more impressive:

$359,246.80

The dollar sign and comma placement are courtesy of the locale settings. These settings determine how large values are expressed and the coin of the realm.

If you change the setlocale() function’s string to en_GB.UTF-8, here is the output:

£359,246.80

And for it_IT.UTF-8:

Eu 359.246,80

In next week’s Lesson, I explore the strfmon() function’s format string options. Alas, my tests met with rather dismal results.

Leave a Reply