Nathaniel R. Stickley

Software Engineer - Astrophysicist - Data Scientist

The {fmt} Library

The standard options for formatting strings in C++ are, frankly, annoying and cumbersome. Yesterday, while using C++ stream format manipulators, I realized that someone must have come up with a clean solution to this common annoyance by now. So, I did a Google search for "C++ python-style string formatting" and eventually found the fmt library (formerly known as cppformat). Fmt is a lightweight library that allows you to use a syntax that is very similar to the string formatting mini-language supported by Python's str.format() function and the Rust language's string formatting syntax.

Here's a simple example:

[cpp] #include

using namespace fmt::literals; // only needed if you are going to use the _a or _format literals.

int main()
{
const int x = 67;

const int y = 45;

const float f = 32.6;

fmt::print("Hello World! This is the number {}\n", x);

fmt::print("This is padded with zeros {:04d} and this is not padded {}\n", x, y);

fmt::print("Floating point formatting with {1} decimal places {0:0.3f}\n", f, 3);

fmt::print(stderr, "{:>25}\n", "Right-aligned"); // printed to the standard error stream

fmt::print("{:>25}\n", "Also right-aligned");

fmt::print("{:^25}\n", "Centered");

// using the _format literal
std::string message = "This is a {0} string that was {0} with {1}.\n"_format("formatted", "literals");

fmt::print(message);

auto first_name = "Nathaniel";

auto last_name = "Stickley";

auto domain_name = "caltech.edu";

// using the _a literal to name the parameters.
fmt::print("My name is {first} {last} ({last}@{domain}).\n",
"first"_a=first_name,
"last"_a=last_name,
"domain"_a=domain_name);

// print color (this is an experimental feature)

fmt::print_colored(fmt::RED, "Error: "); // this prints to the terminal in red.
fmt::print("an error message");

return 0;
}
[/cpp]

The output of the program looks like this:

Hello World! This is the number 67
This is padded with zeros 0067 and this is not padded 45
Floating point formatting with 3 decimal places 32.600
            Right-aligned
       Also right-aligned
        Centered         
This is a formatted string that was formatted with literals.
My name is Nathaniel Stickley (Stickley@caltech.edu).
Error: an error message

Many more usage examples are given in the documentation here and here.

To download the library and install it, I suggest ignoring the instructions on the fmt website and GitHub (if you are running Linux, anyway). Here's a summary of what I did:

[bash] $ git clone https://github.com/fmtlib/fmt.git
$ sudo mkdir /usr/local/include/fmt
$ sudo cp fmt/fmt/format.* /usr/local/include/fmt/
[/bash]

Then, when you compile a program that uses fmt, compile using the header-only library option, by setting FMT_HEADER_ONLY. I suggest this because you may encounter bugs if you try to compile the shared (dynamic) library. For example, to compile the program above, do this:

[bash] $ g++ -O2 --std=c++11 -DFMT_HEADER_ONLY -o hello-world main.cpp
[/bash]

Alternatively, you can put format.h and format.cc in your source directory and #include "format.h" instead of fmt/format.h. Then compile with:

[bash] $ g++ -O2 --std=c++11 -o hello-world main.cpp format.cc
[/bash]

Of course, you may encounter no problems at all when using the shared library, so it's still worth a try.

Nathaniel R. Stickley
nrs@nrstickley.com
626-269-9830