Cldr Print

Provides printf and sprintf functions for Elixir that are largely compatible with the C versions.

Getting Started

Cldr.Print.printf/3, Cldr.Print.sprintf/3 and Cldr.Print.lprintf/3 operate on a format string and a list of arguments to produce a formatted output. The differences are:

  • Cldr.Print.printf/3 outputs to a device specified under the option key :device with :stdout as the default
  • Cldr.Print.sprintf/3 returns an {:ok, string} tuple or an {:error, {exception, reason}} tuple.
  • Cldr.Print.lprintf/3 returns an {:ok, io_list} tuple or an {:error, {exception, reason}} tuple.

There are also ! bang versions of these functions which will return the result unwrapped or raise an exception if there is an error.

Examples

Here are some examples to help get started if you are unfamiliar with the C versions of these functions.

Controlling Integer Width

The %3d specifier is used with integers where the 3 represents the width in graphemes of the final formatted string. These example define a minimum width of three spaces which, by default, will be right-justified:

Function callResult
printf!("%3d", 0)0
printf!("%3d", 123456789)123456789
printf!("%3d", -10)-10
printf!("%3d", -123456789)-123456789

Left-justifying with the - flag

To left-justify an integer add a minus sign - after the % symbol:

Function callResult
printf!("%-3d", 0)0
printf!("%-3d", 123456789)123456789
printf!("%-3d", -10)-10
printf!("%-3d", -123456789)-123456789

Zero-fill flag

To zero-fill the result add a zero 0 after the % symbol:

Function callResult
printf("%03d", 0)000
printf("%03d", 1)001
printf("%03d", 123456789)123456789
printf("%03d", -10)-10
printf("%03d", -123456789)-123456789

Integer formatting summary

Here are some further examples including a minimum width specification, left-justified, zero-filled, as well as a plus sign for positive numbers.

DescriptionFunction callResult
At least five wideprintf("'%5d'", 10)' 10'
At least five-wide, left-justifiedprintf("'%-5d'", 10)'10 '
At least five-wide, zero-filledprintf("'%05d'", 10)'00010'
At least five-wide, with a plus signprintf("'%+5d'", 10)' +10'
Five-wide, plus sign, left-justifiedprintf("'%-+5d'", 10)'+10 '

Floating Point Formatting

Here are several examples showing how to format floating-point numbers:

DescriptionFunction callResult
Print one position after the decimalprintf("'%.1f'", 10.3456)'10.3'
Two positions after the decimalprintf("'%.2f'", 10.3456)'10.35'
Eight-wide, two positions after the decimalprintf("'%8.2f'", 10.3456)' 10.35'
Eight-wide, four positions after the decimalprintf("'%8.4f'", 10.3456)' 10.3456'
Eight-wide, two positions after the decimal, zero-filledprintf("'%08.2f'", 10.3456)'00010.35'
Eight-wide, two positions after the decimal, left-justifiedprintf("'%-8.2f'", 10.3456)'10.35 '
Printing a much larger number with that same formatprintf("'%-8.2f'",101234567.3456)'101234567.35'

String Formatting

Here are some examples of string formatting:

DescriptionFunction callResult
A simple stringprintf("'%s'", "Hello")'Hello'
A string with a minimum lengthprintf("'%10s'", "Hello")' Hello'
Minimum length, left-justifiedprintf("'%-10s'", "Hello")'Hello '

Format Specification

The format is a string which contains two types of objects: plain characters, which are simply copied to standard output and format specifications, each of which causes printing of the next successive argument.

Each format specification is introduced by the percent character (%). The remainder of the format specification includes, in the following order:

  • Optional format flags
  • Optional field width
  • Optional precision
  • Required format type

The can be represented as:

%[flags][width][.precision]format_type

Format flags

Zero or more of the following flags:

FlagDescription
#A # character specifying that the value should be printed in an alternate form. For b, c, d, s and u formats, this option has no effect. For the o formats the precision of the number is increased to force the first character of the output string to a zero. For the x (X) format, a non-zero result has the string 0x (0X) prepended to it. For a, A, e, E, f, F, g and G formats, the result will always contain a decimal point, even if no digits follow the point (normally, a decimal point only appears in the results of those formats if a digit follows the decimal point). For g and G formats, trailing zeros are not removed from the result as they would otherwise be.
-A minus sign `-' which specifies left adjustment of the output in the indicated field.
+A + character specifying that there should always be a sign placed before the number when using signed formats.
spaceA space character specifying that a blank should be left before a positive number for a signed format. A + overrides a space if both are used.
0A zero 0 character indicating that zero-padding should be used rather than blank-padding. A - overrides a 0 if both are used. Is not applied for o, x, X formats.
'Formats a number with digit grouping applied. The group size and grouping character are determined based upon the current processes locale or the :locale option to printf/3 if provided. Is not applied for formats o, x, X formats.
IFormats a number using the native number system digits of the current processes locale or the :locale option to printf/3 if provided. The option :number_system if provided takes precedence over this flag.

Field Width

An optional digit string specifying a field width; if the output string has fewer bytes than the field width it will be blank-padded on the left (or right, if the left-adjustment indicator has been given) to make up the field width (note that a leading zero is a flag, but an embedded zero is part of a field width).

Precision

An optional period, ., followed by an optional digit string giving a precision which specifies the number of digits to appear after the decimal point, for e and f formats, or the maximum number of graphemes to be printed from a string. If the digit string is missing, the precision is treated as zero.

Format Type

A character which indicates the type of format to use (one of diouxXfFeEgGaAs). The uppercase formats differ from their lowercase counterparts only in that the output of the former is entirely in uppercase.

FormatDescription
diouXxThe argument is printed as a signed decimal (d or i), unsigned octal, unsigned decimal, or unsigned hexadecimal (X or x), respectively.
fFThe argument is printed in the style [-]ddd.ddd where the number of d's after the decimal point is equal to the precision specification for the argument. If the precision is missing, 6 digits are given; if the precision is explicitly 0, no digits and no decimal point are printed. The values infinity and NaN are printed as inf' andnan', respectively.
eEThe argument is printed in the style e [-d.ddd+-dd] where there is one digit before the decimal point and the number after is equal to the precision specification for the argument; when the precision is missing, 6 digits are produced. The values infinity and NaN are printed as inf and nan, respectively.
gGThe argument is printed in style f or e (or in style E for a G format code), with the precision specifying the number of significant digits. The style used depends on the value converted: style e will be used only if the exponent resulting from the conversion is less than -4 or greater than the precision. Trailing zeroes are removed from the result; a decimal point appears only if it is followed by a digit.
aAThe argument is printed in style [-h.hhh+-pd] where there is one digit before the hexadecimal point and the number after is equal to the precision specification for the argument; when the precision is missing, enough digits are produced to convey the argument's exact double-precision floating-point representation. The values infinity and NaN are printed as inf and nan, respectively.
sGraphemes from the string argument are printed until the end is reached or until the number of graphemes indicated by the precision specification is reached; however if the precision is 0 or missing, the string is printed entirely.
%Print a %; no argument is used.

Notes

  • The grouping separator, decimal point and exponent characters are defined in the current process's locale or as specified in the :locale option to printf/3.

  • In no case does a non-existent or small field width cause truncation of a field; padding takes place only if the specified field width exceeds the actual width.

Todo

  • [ ] Formats a and A aren't implemented

  • [ ] The # is not validated for a, A, e, E, f, F, g and G formats. There seems to be some inconsistent implementations around that need further investigation

  • [ ] The space flag is not implemented

Installation

def deps do
  [
    {:ex_cldr_print, "~> 0.3.0"}
  ]
end

The documentation can be found at https://hexdocs.pm/ex_cldr_print.