GNU Info

Info Node: (libc.info)Formatting Numbers

(libc.info)Formatting Numbers


Next: Yes-or-No Questions Prev: Locale Information Up: Locales
Enter node , (file) or (file)node

A dedicated function to format numbers
======================================

   We have seen that the structure returned by `localeconv' as well as
the values given to `nl_langinfo' allow you to retrieve the various
pieces of locale-specific information to format numbers and monetary
amounts.  We have also seen that the underlying rules are quite complex.

   Therefore the X/Open standards introduce a function which uses such
locale information, making it easier for the user to format numbers
according to these rules.

 - Function: ssize_t strfmon (char *S, size_t MAXSIZE, const char
          *FORMAT, ...)
     The `strfmon' function is similar to the `strftime' function in
     that it takes a buffer, its size, a format string, and values to
     write into the buffer as text in a form specified by the format
     string.  Like `strftime', the function also returns the number of
     bytes written into the buffer.

     There are two differences: `strfmon' can take more than one
     argument, and, of course, the format specification is different.
     Like `strftime', the format string consists of normal text, which
     is output as is, and format specifiers, which are indicated by a
     `%'.  Immediately after the `%', you can optionally specify
     various flags and formatting information before the main
     formatting character, in a similar way to `printf':

        * Immediately following the `%' there can be one or more of the
          following flags:
         `=F'
               The single byte character F is used for this field as
               the numeric fill character.  By default this character
               is a space character.  Filling with this character is
               only performed if a left precision is specified.  It is
               not just to fill to the given field width.

         `^'
               The number is printed without grouping the digits
               according to the rules of the current locale.  By
               default grouping is enabled.

         `+', `('
               At most one of these flags can be used.  They select
               which format to represent the sign of a currency amount.
               By default, and if `+' is given, the locale equivalent
               of +/- is used.  If `(' is given, negative amounts are
               enclosed in parentheses.  The exact format is determined
               by the values of the `LC_MONETARY' category of the
               locale selected at program runtime.

         `!'
               The output will not contain the currency symbol.

         `-'
               The output will be formatted left-justified instead of
               right-justified if it does not fill the entire field
               width.

     The next part of a specification is an optional field width.  If no
     width is specified 0 is taken.  During output, the function first
     determines how much space is required.  If it requires at least as
     many characters as given by the field width, it is output using as
     much space as necessary.  Otherwise, it is extended to use the
     full width by filling with the space character.  The presence or
     absence of the `-' flag determines the side at which such padding
     occurs.  If present, the spaces are added at the right making the
     output left-justified, and vice versa.

     So far the format looks familiar, being similar to the `printf' and
     `strftime' formats.  However, the next two optional fields
     introduce something new.  The first one is a `#' character followed
     by a decimal digit string.  The value of the digit string
     specifies the number of _digit_ positions to the left of the
     decimal point (or equivalent).  This does _not_ include the
     grouping character when the `^' flag is not given.  If the space
     needed to print the number does not fill the whole width, the
     field is padded at the left side with the fill character, which
     can be selected using the `=' flag and by default is a space.  For
     example, if the field width is selected as 6 and the number is
     123, the fill character is `*' the result will be `***123'.

     The second optional field starts with a `.' (period) and consists
     of another decimal digit string.  Its value describes the number of
     characters printed after the decimal point.  The default is
     selected from the current locale (`frac_digits',
     `int_frac_digits', see Note: General Numeric).  If the exact
     representation needs more digits than given by the field width,
     the displayed value is rounded.  If the number of fractional
     digits is selected to be zero, no decimal point is printed.

     As a GNU extension, the `strfmon' implementation in the GNU libc
     allows an optional `L' next as a format modifier.  If this modifier
     is given, the argument is expected to be a `long double' instead of
     a `double' value.

     Finally, the last component is a format specifier.  There are three
     specifiers defined:

    `i'
          Use the locale's rules for formatting an international
          currency value.

    `n'
          Use the locale's rules for formatting a national currency
          value.

    `%'
          Place a `%' in the output.  There must be no flag, width
          specifier or modifier given, only `%%' is allowed.

     As for `printf', the function reads the format string from left to
     right and uses the values passed to the function following the
     format string.  The values are expected to be either of type
     `double' or `long double', depending on the presence of the
     modifier `L'.  The result is stored in the buffer pointed to by S.
     At most MAXSIZE characters are stored.

     The return value of the function is the number of characters
     stored in S, including the terminating `NULL' byte.  If the number
     of characters stored would exceed MAXSIZE, the function returns -1
     and the content of the buffer S is unspecified.  In this case
     `errno' is set to `E2BIG'.

   A few examples should make clear how the function works.  It is
assumed that all the following pieces of code are executed in a program
which uses the USA locale (`en_US').  The simplest form of the format
is this:

     strfmon (buf, 100, "@%n@%n@%n@", 123.45, -567.89, 12345.678);

The output produced is
     "@$123.45@-$567.89@$12,345.68@"

   We can notice several things here.  First, the widths of the output
numbers are different.  We have not specified a width in the format
string, and so this is no wonder.  Second, the third number is printed
using thousands separators.  The thousands separator for the `en_US'
locale is a comma.  The number is also rounded.  .678 is rounded to .68
since the format does not specify a precision and the default value in
the locale is 2.  Finally, note that the national currency symbol is
printed since `%n' was used, not `i'.  The next example shows how we
can align the output.

     strfmon (buf, 100, "@%=*11n@%=*11n@%=*11n@", 123.45, -567.89, 12345.678);

The output this time is:

     "@    $123.45@   -$567.89@ $12,345.68@"

   Two things stand out.  Firstly, all fields have the same width
(eleven characters) since this is the width given in the format and
since no number required more characters to be printed.  The second
important point is that the fill character is not used.  This is
correct since the white space was not used to achieve a precision given
by a `#' modifier, but instead to fill to the given width.  The
difference becomes obvious if we now add a width specification.

     strfmon (buf, 100, "@%=*11#5n@%=*11#5n@%=*11#5n@",
              123.45, -567.89, 12345.678);

The output is

     "@ $***123.45@-$***567.89@ $12,456.68@"

   Here we can see that all the currency symbols are now aligned, and
that the space between the currency sign and the number is filled with
the selected fill character.  Note that although the width is selected
to be 5 and 123.45 has three digits left of the decimal point, the
space is filled with three asterisks.  This is correct since, as
explained above, the width does not include the positions used to store
thousands separators.  One last example should explain the remaining
functionality.

     strfmon (buf, 100, "@%=0(16#5.3i@%=0(16#5.3i@%=0(16#5.3i@",
              123.45, -567.89, 12345.678);

This rather complex format string produces the following output:

     "@ USD 000123,450 @(USD 000567.890)@ USD 12,345.678 @"

   The most noticeable change is the alternative way of representing
negative numbers.  In financial circles this is often done using
parentheses, and this is what the `(' flag selected.  The fill
character is now `0'.  Note that this `0' character is not regarded as
a numeric zero, and therefore the first and second numbers are not
printed using a thousands separator.  Since we used the format
specifier `i' instead of `n', the international form of the currency
symbol is used.  This is a four letter string, in this case `"USD "'.
The last point is that since the precision right of the decimal point
is selected to be three, the first and second numbers are printed with
an extra zero at the end and the third number is printed without
rounding.


automatically generated by info2www version 1.2.2.9