Pure Programmer
Blue Matrix


Cluster Map

Output Formatting

We have seen the basic ability to convert values to strings and output them to the console ([[stdout]]). Sometimes, however, we would like more control on the formatting used to output values. Fortunately we have formatted output functions that help us with that goal.

C-Style printf()

In the olden days when the C language was developed in the 1970's it contained a novel new way of formatting output called the printf() function. This function allows one to specify a format string followed by values that will be substituted into the format string based on the type specifiers found in the format string. This approach has proven very popular and has been copied in many languages since.

With formatted output we must provide a format string that can contain literal text interspersed with type specifiers. The type specifiers are placeholders that identify where and how a value is to be formatted and inserted into the string on output. Type specifiers start with a percent sign (%), followed by an optional flag, followed by field width and/or precision, followed by one or two characters identifying the type of the value (called the type specifier). Only the percent sign and the type specifier is required, the other components are optional.

%[flag][width][.precision][type specifier]

In addition to the format string, we also provide the values to be formatted to the function. We can have multiple type specifiers in the format string as long as we provide the matching number of additional arguments. The first argument is formatted by the first type specifier, the second argument by the second type specifier, and so on.

printf() Illustration
printf() specifiers must match arguments in order

Any other characters in the format string that are not part of a type specifier are printed verbatim. For example:


Some of the type specifiers available are listed in the table below.

Frequently Used Type Specifiers
SpecifierValue TypeDescription
Print Flags
FlagDescription
-Left-justify within the given field width; Right justification is the default.
+Result is preceeded with a plus or minus sign (+ or -) even for positive numbers. By default, only negative numbers are preceded with a - sign.
#Used with o, x or X specifiers the value is preceeded with 0, 0x or 0X respectively. Used with e, E, f, g or G it forces the written output to contain a decimal point even if no more digits follow. By default, if no digits follow, no decimal point is written.
0Left-pads the number with zeroes (0) instead of spaces

The field width and precision are simply integer values separated by a period (.). One may use either in the type specifier, both or none. Field width sets the number of characters that will be used to output the value padded with spaces if necessary to achieve the field width. The precision specifier is only useful for formatting floating point and string values. For floating point values it limits the number of decimal places after the decimal point. For strings it truncates the string to the specified number of characters.

OutputFormatting1.rs
fn main() {
	let a:isize = 326;
	let b:isize = -1;
	let c:isize = 2015;
	let i1:i64 = 65000;
	let i2:i64 = -2;
	let i3:i64 = 3261963;
	let f1:f64 = 3.1415926f64;
	let f2:f64 = 2.99792458e9f64;
	let f3:f64 = 1.234e-4f64;
	let c1:i32 = u32('A');
	let c2:i32 = u32('B');
	let c3:i32 = u32('C');
	let s1:&str = "Apples";
	let s2:&str = "and";
	let s3:&str = "Bananas";
	let b1:bool = true;
	let b2:bool = false;

	printf("Decimals: %d %d %d\n",a,b,c);
	printf("Hexadecimals: %#x %#x %#x\n",a,b,c);
	printf("Long Decimals: %d %d %d\n",i1,i2,i3);
	printf("Long Hexadecimals: %016x %016x %016x\n",i1,i2,i3);

	printf("Fixed FP: %f %f %f\n",f1,f2,f3);
	printf("Exponential FP: %e %e %e\n",f1,f2,f3);
	printf("General FP: %g %g %g\n",f1,f2,f3);
	printf("General FP with precision: %.2g %.2g %.2g\n",f1,f2,f3);

	printf("Character: %@ %@ %@\n",char::from_u32(c1),char::from_u32(c2),char::from_u32(c3));
	printf("String: %s %s %s\n",s1,s2,s3);
}

Output
$ rustc OutputFormatting1.rs error[E0423]: expected function, found builtin type `u32` --> OutputFormatting1.rs:11:15 | 11 | let c1:i32 = u32('A'); | ^^^ not a function error[E0423]: expected function, found builtin type `u32` --> OutputFormatting1.rs:12:15 | 12 | let c2:i32 = u32('B'); | ^^^ not a function error[E0423]: expected function, found builtin type `u32` --> OutputFormatting1.rs:13:15 | 13 | let c3:i32 = u32('C'); | ^^^ not a function error[E0425]: cannot find function `printf` in this scope --> OutputFormatting1.rs:20:2 | 20 | printf("Decimals: %d %d %d\n",a,b,c); | ^^^^^^ not found in this scope | help: you may have meant to use the `print` macro | 20 | print!("Decimals: %d %d %d\n",a,b,c); | ~~~~~~ error[E0425]: cannot find function `printf` in this scope --> OutputFormatting1.rs:21:2 | 21 | printf("Hexadecimals: %#x %#x %#x\n",a,b,c); | ^^^^^^ not found in this scope | help: you may have meant to use the `print` macro | 21 | print!("Hexadecimals: %#x %#x %#x\n",a,b,c); | ~~~~~~ error[E0425]: cannot find function `printf` in this scope --> OutputFormatting1.rs:22:2 | 22 | printf("Long Decimals: %d %d %d\n",i1,i2,i3); | ^^^^^^ not found in this scope | help: you may have meant to use the `print` macro | 22 | print!("Long Decimals: %d %d %d\n",i1,i2,i3); | ~~~~~~ error[E0425]: cannot find function `printf` in this scope --> OutputFormatting1.rs:23:2 | 23 | printf("Long Hexadecimals: %016x %016x %016x\n",i1,i2,i3); | ^^^^^^ not found in this scope | help: you may have meant to use the `print` macro | 23 | print!("Long Hexadecimals: %016x %016x %016x\n",i1,i2,i3); | ~~~~~~ error[E0425]: cannot find function `printf` in this scope --> OutputFormatting1.rs:25:2 | 25 | printf("Fixed FP: %f %f %f\n",f1,f2,f3); | ^^^^^^ not found in this scope | help: you may have meant to use the `print` macro | 25 | print!("Fixed FP: %f %f %f\n",f1,f2,f3); | ~~~~~~ error[E0425]: cannot find function `printf` in this scope --> OutputFormatting1.rs:26:2 | 26 | printf("Exponential FP: %e %e %e\n",f1,f2,f3); | ^^^^^^ not found in this scope | help: you may have meant to use the `print` macro | 26 | print!("Exponential FP: %e %e %e\n",f1,f2,f3); | ~~~~~~ error[E0425]: cannot find function `printf` in this scope --> OutputFormatting1.rs:27:2 | 27 | printf("General FP: %g %g %g\n",f1,f2,f3); | ^^^^^^ not found in this scope | help: you may have meant to use the `print` macro | 27 | print!("General FP: %g %g %g\n",f1,f2,f3); | ~~~~~~ error[E0425]: cannot find function `printf` in this scope --> OutputFormatting1.rs:28:2 | 28 | printf("General FP with precision: %.2g %.2g %.2g\n",f1,f2,f3); | ^^^^^^ not found in this scope | help: you may have meant to use the `print` macro | 28 | print!("General FP with precision: %.2g %.2g %.2g\n",f1,f2,f3); | ~~~~~~ error[E0425]: cannot find function `printf` in this scope --> OutputFormatting1.rs:30:2 | 30 | printf("Character: %@ %@ %@\n",char::from_u32(c1),char::from_u32(c2),char::from_u32(c3)); | ^^^^^^ not found in this scope | help: you may have meant to use the `print` macro | 30 | print!("Character: %@ %@ %@\n",char::from_u32(c1),char::from_u32(c2),char::from_u32(c3)); | ~~~~~~ error[E0425]: cannot find function `printf` in this scope --> OutputFormatting1.rs:31:2 | 31 | printf("String: %s %s %s\n",s1,s2,s3); | ^^^^^^ not found in this scope | help: you may have meant to use the `print` macro | 31 | print!("String: %s %s %s\n",s1,s2,s3); | ~~~~~~ error: aborting due to 13 previous errors Some errors have detailed explanations: E0423, E0425. For more information about an error, try `rustc --explain E0423`.

C-Style sprintf()

Along with the printf() function, the C language introduced a similar function called sprintf(). Instead of printing a formatted string to the console ([[stdout]]), it formats and then returns a string. This more general form has many uses not only for console output but for [[GUI]] output and file output.

OutputFormatting2.rs
mod utils;

fn main() {
	let a:isize = 326;
	let b:isize = -1;
	let c:isize = 2015;
	let i1:i64 = 65000;
	let i2:i64 = -2;
	let i3:i64 = 3261963;
	let f1:f64 = 3.1415926f64;
	let f2:f64 = 2.99792458e9f64;
	let f3:f64 = 1.234e-4f64;
	let c1:i32 = u32('A');
	let c2:i32 = u32('B');
	let c3:i32 = u32('C');
	let s1:&str = "Apples";
	let s2:&str = "and";
	let s3:&str = "Bananas";
	let b1:bool = true;
	let b2:bool = false;

	let mut s:&str = "";

	s = &(sprintf("Decimals: %d %d %d",a,b,c));
	println!("{}", s);
	s = &(sprintf("Hexadecimals: %#x %#x %#x",a,b,c));
	println!("{}", s);
	s = &(sprintf("Long Decimals: %d %d %d",i1,i2,i3));
	println!("{}", s);
	s = &(sprintf("Long Hexadecimals: %016x %016x %016x",i1,i2,i3));
	println!("{}", s);

	s = &(sprintf("Fixed FP: %f %f %f",f1,f2,f3));
	println!("{}", s);
	s = &(sprintf("Exponential FP: %e %e %e",f1,f2,f3));
	println!("{}", s);
	s = &(sprintf("General FP: %g %g %g",f1,f2,f3));
	println!("{}", s);
	s = &(sprintf("General FP with precision: %.2g %.2g %.2g",f1,f2,f3));
	println!("{}", s);

	s = &(sprintf("Character: %@ %@ %@",char::from_u32(c1),char::from_u32(c2),char::from_u32(c3)));
	println!("{}", s);
	s = &(sprintf("String: %s %s %s",s1,s2,s3));
	println!("{}", s);
}

Output
$ rustc OutputFormatting2.rs error[E0423]: expected function, found builtin type `u32` --> OutputFormatting2.rs:13:15 | 13 | let c1:i32 = u32('A'); | ^^^ not a function error[E0423]: expected function, found builtin type `u32` --> OutputFormatting2.rs:14:15 | 14 | let c2:i32 = u32('B'); | ^^^ not a function error[E0423]: expected function, found builtin type `u32` --> OutputFormatting2.rs:15:15 | 15 | let c3:i32 = u32('C'); | ^^^ not a function error[E0425]: cannot find function `sprintf` in this scope --> OutputFormatting2.rs:24:8 | 24 | s = &(sprintf("Decimals: %d %d %d",a,b,c)); | ^^^^^^^ not found in this scope error[E0425]: cannot find function `sprintf` in this scope --> OutputFormatting2.rs:26:8 | 26 | s = &(sprintf("Hexadecimals: %#x %#x %#x",a,b,c)); | ^^^^^^^ not found in this scope error[E0425]: cannot find function `sprintf` in this scope --> OutputFormatting2.rs:28:8 | 28 | s = &(sprintf("Long Decimals: %d %d %d",i1,i2,i3)); | ^^^^^^^ not found in this scope error[E0425]: cannot find function `sprintf` in this scope --> OutputFormatting2.rs:30:8 | 30 | s = &(sprintf("Long Hexadecimals: %016x %016x %016x",i1,i2,i3)); | ^^^^^^^ not found in this scope error[E0425]: cannot find function `sprintf` in this scope --> OutputFormatting2.rs:33:8 | 33 | s = &(sprintf("Fixed FP: %f %f %f",f1,f2,f3)); | ^^^^^^^ not found in this scope error[E0425]: cannot find function `sprintf` in this scope --> OutputFormatting2.rs:35:8 | 35 | s = &(sprintf("Exponential FP: %e %e %e",f1,f2,f3)); | ^^^^^^^ not found in this scope error[E0425]: cannot find function `sprintf` in this scope --> OutputFormatting2.rs:37:8 | 37 | s = &(sprintf("General FP: %g %g %g",f1,f2,f3)); | ^^^^^^^ not found in this scope error[E0425]: cannot find function `sprintf` in this scope --> OutputFormatting2.rs:39:8 | 39 | s = &(sprintf("General FP with precision: %.2g %.2g %.2g",f1,f2,f3)); | ^^^^^^^ not found in this scope error[E0425]: cannot find function `sprintf` in this scope --> OutputFormatting2.rs:42:8 | 42 | s = &(sprintf("Character: %@ %@ %@",char::from_u32(c1),char::from_u32(c2),char::from_u32(c3))); | ^^^^^^^ not found in this scope error[E0425]: cannot find function `sprintf` in this scope --> OutputFormatting2.rs:44:8 | 44 | s = &(sprintf("String: %s %s %s",s1,s2,s3)); | ^^^^^^^ not found in this scope error: aborting due to 13 previous errors Some errors have detailed explanations: E0423, E0425. For more information about an error, try `rustc --explain E0423`.

String Interpolation

Many languages have the ability to replace variables written directly into strings. This variable substitution in strings is know as variable interpolation. In Rust we can substitute varibles inside strings that have the prefix f!. One simply wraps the varible name in curly brackets and places it in the string such as {variable_name}. Many macros have the ability to interpolate the first argument such as print_f!() and println_f!().

OutputFormatting3.rs
extern crate fstrings;

fn main() {
	let FICA_RATE:f64 = 0.0765f64;
	let PAY_RATE:f64 = 20.f64;
	let mut annual_salary:f64 = 0.0;

	annual_salary = PAY_RATE * 2080.0f64;
	let mut FICA_tax:f64 = annual_salary * FICA_RATE;
	let mut s1:&str = f!("FICA Tax Rate: {FICA_RATE}");
	println!("{}", s1);
	println!("{}", f!("Annual Salary: {annual_salary}"));
	println_f!("FICA Tax: {FICA_tax}");
}

Output
$ rustc OutputFormatting3.rs error[E0308]: mismatched types --> OutputFormatting3.rs:3:25 | 3 | let annualSalary:f64 = 50000; | --- ^^^^^ | | | | | expected `f64`, found integer | | help: use a float literal: `50000.0` | expected due to this error: aborting due to previous error For more information about this error, try `rustc --explain E0308`. $ rustc OutputFormatting3.rs error: expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `"FICA Tax Rate: {FICA_RATE}"` --> OutputFormatting3.rs:7:18 | 7 | println!("{}", f"FICA Tax Rate: {FICA_RATE}"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected one of 7 possible tokens error: expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `"Annual Salary: {annual_salary}"` --> OutputFormatting3.rs:8:18 | 8 | println!("{}", f"Annual Salary: {annual_salary}"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected one of 7 possible tokens error: cannot find macro `println_f` in this scope --> OutputFormatting3.rs:9:2 | 9 | println_f!("FICA Tax: {FICA_tax}"); | ^^^^^^^^^ help: a macro with a similar name exists: `println` --> /opt/local/libexec/rust/src/rustc-1.71.1-src/library/std/src/macros.rs:132:1 | = note: similarly named macro `println` defined here error[E0308]: mismatched types --> OutputFormatting3.rs:5:18 | 3 | let mut annual_salary:f64 = 0.0; | --- expected due to this type 4 | 5 | annual_salary = 20 * 2080; | ^^^^^^^^^ expected `f64`, found integer error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0308`. $ rustc OutputFormatting3.rs error: mismatched closing delimiter: `)` --> OutputFormatting3.rs:1:11 | 1 | fn main() { | ^ unclosed delimiter ... 9 | println!("{}", f!("Annual Salary: {annual_salary})); | ^ mismatched closing delimiter error: unexpected closing delimiter: `}` --> OutputFormatting3.rs:11:1 | 9 | println!("{}", f!("Annual Salary: {annual_salary})); | - missing open `(` for this delimiter 10 | println_f!("FICA Tax: {FICA_tax}"); 11 | } | ^ unexpected closing delimiter error: aborting due to 2 previous errors $ rustc OutputFormatting3.rs error: cannot find macro `f` in this scope --> OutputFormatting3.rs:7:20 | 7 | let mut s1:&str = f!("FICA Tax Rate: {FICA_RATE}"); | ^ error: cannot find macro `f` in this scope --> OutputFormatting3.rs:9:17 | 9 | println!("{}", f!("Annual Salary: {annual_salary}")); | ^ error: cannot find macro `println_f` in this scope --> OutputFormatting3.rs:10:2 | 10 | println_f!("FICA Tax: {FICA_tax}"); | ^^^^^^^^^ help: a macro with a similar name exists: `println` --> /opt/local/libexec/rust/src/rustc-1.71.1-src/library/std/src/macros.rs:132:1 | = note: similarly named macro `println` defined here error: aborting due to 3 previous errors $ rustc OutputFormatting3.rs error: cannot find macro `f` in this scope --> OutputFormatting3.rs:7:20 | 7 | let mut s1:&str = f!("FICA Tax Rate: {FICA_RATE}"); | ^ error: cannot find macro `f` in this scope --> OutputFormatting3.rs:9:17 | 9 | println!("{}", f!("Annual Salary: {annual_salary}")); | ^ error: cannot find macro `println_f` in this scope --> OutputFormatting3.rs:10:2 | 10 | println_f!("FICA Tax: {FICA_tax}"); | ^^^^^^^^^ help: a macro with a similar name exists: `println` --> /opt/local/libexec/rust/src/rustc-1.71.1-src/library/std/src/macros.rs:132:1 | = note: similarly named macro `println` defined here error: aborting due to 3 previous errors

Modern Message Formatting

The methods for formatting strings and output discuss so far have some limitations when it comes to localizing software. The positional approaches taken by the printf() style functions poses difficulties to localization because often during translation the order of words and thus the substition specifiers must change but the hard-code argument list in our code can not change to match. Variable interpolation has its drawbacks because you are actually putting code into the strings. When externalizing the strings (removing them from the code and putting them in a separate file) necessary for localization, it is not desirable to export variables and expressions from our code to the localization file where they can be changed.

This is why message formatting approaches have been developed that use substitution specifiers that specify which argument to the message format function is to be used. This allows the substitution specifiers to be in a different order (and perhaps re-ordered during localization) than the formal arguments to the message format function. These substitution specifiers are also not executable code as is the case with variable interpolation so it is much safer to externalize from our program code as we will see in the section on Internationalization.

The format() method uses a pair of curly brackets to identify substition placeholders in the format string. Each pair of curly brackets contains a number from 0 to the number of addtional arguments - 1. This number refers to the position in the argument list of the value that will be used in the substitution. This allows values in the argument list to be used in any order needed in the format string or even used more than once.

format() Illustration
format() specifiers can match any argument

Following the position number in the substitution placeholder is an optional type specifier. The type specifier is separated from the position number by a colon. If you don't wish to use a type specifier then the type is assumed to be string. Some of the type specifiers available are listed in the table below.

Frequently Used Type Specifiers
SpecifierValue TypeDescription
bintegerbinary
dintegerdecimal
ointegeroctal
xintegerhexadecimal (lowercase)
Xintegerhexadecimal (uppercase)
fdoublefixed notation
edoublescientific notation (lowercase)
Edoublescientific notation (uppercase)
gdoubleshortest representation: e or f
Gdoubleshortest representation: E or f
cintegersingle character
sstringstring of characters

Like we have seen in printf(), the format() specifiers can take optional modifiers that change how the value is to be formatted. The full definition of the specifiers, including optional components is as follows:

{[arg-pos]:[fill-and-align][sign][#][0][width][.precision][type specifier]}

The fill-and-align option is an optional fill character (which can be any character other than { or }), followed by one of the align options <, >, ^. If no fill character is specified, then the space character is used.

Align Options
OptionDescription
<Left-justify within the given field width. This is the default for non-numeric types.
>Right-justify within the given field width. This is the default for numeric types.
^Aligns the value in the center of the field.

The sign option is one of +, - or the space character.

Sign Options
OptionDescription
+Signifies that a sign character should be output for all values (+ for positive and - for negative).
-Signifies that a sign character should be output for negative values only. This is the default for numeric types.
<space>Signifies that a leading space should be used for positive values and a - should be output for negative values.

The # option causes alternate formatting to be used.

The 0 option pads the field with leading zeros (following any indication of sign or base) to the field width. If the 0 option and an align option both are used, the 0 option is ignored.

The width option is a positive decimal number. If present, it specifies the minimum field width. If the formatted value can not fit within the field width the entire value will be inserted causing the field to be larger than width.

The precision option is a . followed by a non-negative decimal number. This option indicates the precision to use when formatting a value. For floating-point types, precision specifies the formatting precision, i.e. the number of places after the decimal point to display. For string types, it specifies how many characters from the string will be used.

OutputFormatting4.rs
fn main() {
	let first:&str = "First";
	let middle:&str = "Middle";
	let lastname:&str = "Last";
	let left:&str = "Left";
	let center:&str = "Center";
	let right:&str = "Right";
	let favorite:&str = "kerfuffle";
	let i1:i64 = 3261963;
	let i2:i16 = -42;
	let fp1:f64 = 3.1415926f64;
	let fp2:f64 = 2.99792458e9f64;
	let fp3:f64 = -1.234e-4f64;

	let mut s:String = format!("{2}, {0} {1}", first, middle, lastname);
	println!("{}", s);
	s = format!("{0} {1} {2}", left, center, right);
	println!("{}", s);
	s = format!("Favorite number is {0}", i1);
	println!("{}", s);
	s = format!("Favorite FP is {0}", fp1);
	println!("{}", s);

	let mut c:i32 = favorite[0];
	println!("{}", format!("Favorite c is {0:c}", c));
	println!("{}", format!("Favorite 11c is   |{0:11c}|", c));
	println!("{}", format!("Favorite <11c is  |{0:<11c}|", c));
	println!("{}", format!("Favorite ^11c is  |{0:^11c}|", c));
	println!("{}", format!("Favorite >11c is  |{0:>11c}|", c));
	println!("{}", format!("Favorite .<11c is |{0:.<11c}|", c));
	println!("{}", format!("Favorite _^11c is |{0:_^11c}|", c));
	println!("{}", format!("Favorite  >11c is |{0: >11c}|", c));

	c = 0x1F92F;
	println!("{}", format!("Favorite emoji c is {0:c}", c));

	println!("{}", format!("Favorite s is {0:s}", favorite));
	println!("{}", format!("Favorite .2s is {0:.2s}", favorite));
	println!("{}", format!("Favorite 11s is     |{0:11s}|", favorite));
	println!("{}", format!("Favorite 11.2s is   |{0:11.2s}|", favorite));
	println!("{}", format!("Favorite <11.2s is  |{0:<11.2s}|", favorite));
	println!("{}", format!("Favorite ^11.2s is  |{0:^11.2s}|", favorite));
	println!("{}", format!("Favorite >11.2s is  |{0:>11.2s}|", favorite));
	println!("{}", format!("Favorite .<11.2s is |{0:.<11.2s}|", favorite));
	println!("{}", format!("Favorite *^11.2s is |{0:*^11.2s}|", favorite));
	println!("{}", format!("Favorite ->11.2s is |{0:->11.2s}|", favorite));

	println!("{}", format!("Favorite d is {0:d}", i1));
	println!("{}", format!("Another d is {0:d}", i2));
	println!("{}", format!("Favorite b is {0:b}", i1));
	println!("{}", format!("Another B is {0:b}", i2));
	println!("{}", format!("Favorite o is {0:o}", i1));
	println!("{}", format!("Another o is {0:o}", i2));
	println!("{}", format!("Favorite x is {0:x}", i1));
	println!("{}", format!("Another X is {0:X}", i2));
	println!("{}", format!("Favorite #b is {0:#b}", i1));
	println!("{}", format!("Another #B is {0:#b}", i2));
	println!("{}", format!("Favorite #o is {0:#o}", i1));
	println!("{}", format!("Another #o is {0:#o}", i2));
	println!("{}", format!("Favorite #x is {0:#x}", i1));
	println!("{}", format!("Another #X is {0:#X}", i2));
	println!("{}", format!("Favorite 11d is   |{0:11d}|", i1));
	println!("{}", format!("Favorite +11d is  |{0:+11d}|", i1));
	println!("{}", format!("Favorite 011d is  |{0:011d}|", i1));
	println!("{}", format!("Favorite 011x is  |{0:011x}|", i1));
	println!("{}", format!("Favorite #011x is |{0:#011x}|", i1));

	println!("{}", format!("Favorite f is {0:f}", fp1));
	println!("{}", format!("Another f is {0:f}", fp2));
	println!("{}", format!("One more f is {0:f}", fp3));
	println!("{}", format!("Favorite e is {0:e}", fp1));
	println!("{}", format!("Another e is {0:e}", fp2));
	println!("{}", format!("One more e is {0:e}", fp3));
	println!("{}", format!("Favorite g is {0:g}", fp1));
	println!("{}", format!("Another g is {0:g}", fp2));
	println!("{}", format!("One more g is {0:g}", fp3));
	println!("{}", format!("Favorite .2f is {0:.2f}", fp1));
	println!("{}", format!("Another .2f is {0:.2f}", fp2));
	println!("{}", format!("One more .2f is {0:.2f}", fp3));
	println!("{}", format!("Favorite .2e is {0:.2e}", fp1));
	println!("{}", format!("Another .2e is {0:.2e}", fp2));
	println!("{}", format!("One more .2e is {0:.2e}", fp3));
	println!("{}", format!("Favorite .2g is {0:.2g}", fp1));
	println!("{}", format!("Another .2g is {0:.2g}", fp2));
	println!("{}", format!("One more .2g is {0:.2g}", fp3));
	println!("{}", format!("Favorite 15.2f is |{0:15.2f}|", fp1));
	println!("{}", format!("Another 15.2e is  |{0:15.2e}|", fp2));
	println!("{}", format!("One more 15.2g is |{0:15.2g}|", fp3));
}

Output
$ rustc OutputFormatting4.rs error: unknown format trait `c` --> OutputFormatting4.rs:25:43 | 25 | println!("{}", format!("Favorite c is {0:c}", c)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error: unknown format trait `c` --> OutputFormatting4.rs:26:50 | 26 | println!("{}", format!("Favorite 11c is |{0:11c}|", c)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error: unknown format trait `c` --> OutputFormatting4.rs:27:51 | 27 | println!("{}", format!("Favorite <11c is |{0:<11c}|", c)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error: unknown format trait `c` --> OutputFormatting4.rs:28:51 | 28 | println!("{}", format!("Favorite ^11c is |{0:^11c}|", c)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error: unknown format trait `c` --> OutputFormatting4.rs:29:51 | 29 | println!("{}", format!("Favorite >11c is |{0:>11c}|", c)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error: unknown format trait `c` --> OutputFormatting4.rs:30:52 | 30 | println!("{}", format!("Favorite .<11c is |{0:.<11c}|", c)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error: unknown format trait `c` --> OutputFormatting4.rs:31:52 | 31 | println!("{}", format!("Favorite _^11c is |{0:_^11c}|", c)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error: unknown format trait `c` --> OutputFormatting4.rs:32:52 | 32 | println!("{}", format!("Favorite >11c is |{0: >11c}|", c)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error: unknown format trait `c` --> OutputFormatting4.rs:35:49 | 35 | println!("{}", format!("Favorite emoji c is {0:c}", c)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error: unknown format trait `s` --> OutputFormatting4.rs:37:43 | 37 | println!("{}", format!("Favorite s is {0:s}", favorite)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error: unknown format trait `s` --> OutputFormatting4.rs:38:47 | 38 | println!("{}", format!("Favorite .2s is {0:.2s}", favorite)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error: unknown format trait `s` --> OutputFormatting4.rs:39:52 | 39 | println!("{}", format!("Favorite 11s is |{0:11s}|", favorite)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error: unknown format trait `s` --> OutputFormatting4.rs:40:54 | 40 | println!("{}", format!("Favorite 11.2s is |{0:11.2s}|", favorite)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error: unknown format trait `s` --> OutputFormatting4.rs:41:55 | 41 | println!("{}", format!("Favorite <11.2s is |{0:<11.2s}|", favorite)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error: unknown format trait `s` --> OutputFormatting4.rs:42:55 | 42 | println!("{}", format!("Favorite ^11.2s is |{0:^11.2s}|", favorite)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error: unknown format trait `s` --> OutputFormatting4.rs:43:55 | 43 | println!("{}", format!("Favorite >11.2s is |{0:>11.2s}|", favorite)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error: unknown format trait `s` --> OutputFormatting4.rs:44:56 | 44 | println!("{}", format!("Favorite .<11.2s is |{0:.<11.2s}|", favorite)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error: unknown format trait `s` --> OutputFormatting4.rs:45:56 | 45 | println!("{}", format!("Favorite *^11.2s is |{0:*^11.2s}|", favorite)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error: unknown format trait `s` --> OutputFormatting4.rs:46:56 | 46 | println!("{}", format!("Favorite ->11.2s is |{0:->11.2s}|", favorite)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error: unknown format trait `d` --> OutputFormatting4.rs:48:43 | 48 | println!("{}", format!("Favorite d is {0:d}", i1)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error: unknown format trait `d` --> OutputFormatting4.rs:49:42 | 49 | println!("{}", format!("Another d is {0:d}", i2)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error: unknown format trait `d` --> OutputFormatting4.rs:62:50 | 62 | println!("{}", format!("Favorite 11d is |{0:11d}|", i1)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error: unknown format trait `d` --> OutputFormatting4.rs:63:51 | 63 | println!("{}", format!("Favorite +11d is |{0:+11d}|", i1)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error: unknown format trait `d` --> OutputFormatting4.rs:64:51 | 64 | println!("{}", format!("Favorite 011d is |{0:011d}|", i1)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error: unknown format trait `f` --> OutputFormatting4.rs:68:43 | 68 | println!("{}", format!("Favorite f is {0:f}", fp1)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error: unknown format trait `f` --> OutputFormatting4.rs:69:42 | 69 | println!("{}", format!("Another f is {0:f}", fp2)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error: unknown format trait `f` --> OutputFormatting4.rs:70:43 | 70 | println!("{}", format!("One more f is {0:f}", fp3)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error: unknown format trait `g` --> OutputFormatting4.rs:74:43 | 74 | println!("{}", format!("Favorite g is {0:g}", fp1)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error: unknown format trait `g` --> OutputFormatting4.rs:75:42 | 75 | println!("{}", format!("Another g is {0:g}", fp2)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error: unknown format trait `g` --> OutputFormatting4.rs:76:43 | 76 | println!("{}", format!("One more g is {0:g}", fp3)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error: unknown format trait `f` --> OutputFormatting4.rs:77:47 | 77 | println!("{}", format!("Favorite .2f is {0:.2f}", fp1)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error: unknown format trait `f` --> OutputFormatting4.rs:78:46 | 78 | println!("{}", format!("Another .2f is {0:.2f}", fp2)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error: unknown format trait `f` --> OutputFormatting4.rs:79:47 | 79 | println!("{}", format!("One more .2f is {0:.2f}", fp3)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error: unknown format trait `g` --> OutputFormatting4.rs:83:47 | 83 | println!("{}", format!("Favorite .2g is {0:.2g}", fp1)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error: unknown format trait `g` --> OutputFormatting4.rs:84:46 | 84 | println!("{}", format!("Another .2g is {0:.2g}", fp2)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error: unknown format trait `g` --> OutputFormatting4.rs:85:47 | 85 | println!("{}", format!("One more .2g is {0:.2g}", fp3)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error: unknown format trait `f` --> OutputFormatting4.rs:86:52 | 86 | println!("{}", format!("Favorite 15.2f is |{0:15.2f}|", fp1)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error: unknown format trait `g` --> OutputFormatting4.rs:88:52 | 88 | println!("{}", format!("One more 15.2g is |{0:15.2g}|", fp3)); | ^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait - `?`, which uses the `Debug` trait - `e`, which uses the `LowerExp` trait - `E`, which uses the `UpperExp` trait - `o`, which uses the `Octal` trait - `p`, which uses the `Pointer` trait - `b`, which uses the `Binary` trait - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait error[E0277]: the type `str` cannot be indexed by `{integer}` --> OutputFormatting4.rs:24:27 | 24 | let mut c:i32 = favorite[0]; | ^ string indices are ranges of `usize` | = help: the trait `SliceIndex<str>` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings> = help: the trait `SliceIndex<[T]>` is implemented for `usize` = note: required for `str` to implement `Index<{integer}>` error: aborting due to 39 previous errors For more information about this error, try `rustc --explain E0277`.

Questions

Projects

More ★'s indicate higher difficulty level.

References