Lecture 14 — std::format and std::print
Source: sc++/ch10.md Duration: 75 minutes
Learning Objectives
By the end of this lecture, students should be able to:
- Use
std::formatwith{}placeholders to produce formatted strings - Distinguish implicit (
{}) and indexed ({0},{1}) argument numbering — and remember they cannot be mixed - Apply format specifiers for width, alignment (
<,>,^), fill characters, sign, and base prefix - Control floating-point precision with
{:.Nf}and integer base with{:x},{:o},{:b} - Use
std::printandstd::printlnto print formatted output in one call
Materials
- Live coding terminal with
g++(-std=c++23 -Wall -Wextra -pedantic) — C++23 is required for<print> - A text editor projected for the class
- Copies of
sc++/ch10.mdfor reference
0. Welcome and Review (5 min)
Review multiple choice (from lecture 13): What is wrong with this file-writing code?
std::ofstream out; out << "Yo me la paso bien\n"; out.close();- A. Missing
#include <fstream> - B. No filename was passed to the constructor — the stream is not attached to a file
- C.
\nshould bestd::endl - D. You cannot
<<to anofstream - E. Ben got this wrong
Answer: B
- A. Missing
Last lecture we saw streams and
std::setw/std::setprecision. Today we replace them with something much nicer.
1. Motivation (5 min)
// old way --- hard to read
std::cout << std::fixed << std::setprecision(2)
<< std::setw(10) << score << "\n";
// new way --- much clearer
std::println("{:10.2f}", score);- Chaining
<<with manipulators is verbose and sticky std::format(C++20) andstd::print/std::println(C++23) give you clean format strings
2. std::format Basics (8 min)
Include <format>. Returns a std::string.
#include <format>
#include <iostream>
#include <string>
int main()
{
std::string artist = "Santana";
int year = 1999;
std::string msg = std::format("{} --- Smooth ({})", artist, year);
std::cout << msg << "\n";
// Santana --- Smooth (1999)
}{}placeholders are substituted in order (implicit numbering)- Each argument can be any type the library knows how to format
3. Indexed Arguments (6 min)
std::format("{1} --- {0} ({2})", "Santana", "Smooth", 1999);
// "Smooth --- Santana (1999)"
std::format("{0}, {0}, {0}!", "yeah");
// "yeah, yeah, yeah!"- Numbers inside the braces are zero-based argument indices
- Great for reordering or repeating arguments
Trap: You cannot mix implicit {} and indexed {0} in the same format string. std::format("{},{1}", 1, "hi") is a compile error. Pick one style.
4. Format Specifiers — Width and Alignment (10 min)
The general form is {index:spec} where spec is [[fill]align][sign][#][0][width][.prec][type].
std::format("{:>10}", "hola"); // " hola" (right-align)
std::format("{:<10}", "hola"); // "hola " (left-align)
std::format("{:^10}", "hola"); // " hola " (center)Fill Characters
std::format("{:*>10}", "hola"); // "******hola"
std::format("{:-^20}", "Smooth"); // "-------Smooth-------"fillis any character,alignis<,>, or^- Omit
filland you get a space
5. Format Specifiers — Numbers (10 min)
Sign
std::format("{:+}", 42); // "+42" (always show sign)
std::format("{:-}", 42); // "42" (default)
std::format("{: }", 42); // " 42" (space where + would go)Alternate Form and Zero-padding
std::format("{:#x}", 255); // "0xff"
std::format("{:#b}", 10); // "0b1010"
std::format("{:05}", 42); // "00042"
std::format("{:#010x}", 255); // "0x000000ff"Base Types
std::format("{:d}", 42); // "42" (decimal)
std::format("{:x}", 255); // "ff" (hex)
std::format("{:o}", 8); // "10" (octal)
std::format("{:b}", 10); // "1010"(binary)6. Floating-Point Precision (8 min)
std::format("{:.2f}", 3.14159); // "3.14"
std::format("{:.4f}", 2.5); // "2.5000"
std::format("{:10.2f}", 3.14); // " 3.14".Ncontrols decimal placesfis fixed-point; omit for default “general” formatting- Combine with width/alignment as needed
7. std::print and std::println (C++23) (10 min)
Include <print>. Combine std::format and std::cout in one call.
#include <print>
int main()
{
std::println("You get what you give, don't let go");
std::print("Track {:d}: {}", 1, "You Get What You Give");
std::println("");
double score = 9.5;
std::println("Rating: {:.1f}/10", score);
}std::print— no trailing newlinestd::println— adds a newline
Wut: std::print and std::println require C++23. If your compiler does not have <print> yet, fall back to std::cout << std::format(...).
8. Try It — Formatted Table (10 min)
#include <format>
#include <iostream>
int main()
{
std::cout << std::format("{:<20} {:>5} {:>8}\n", "Song", "Year", "Score");
std::cout << std::string(35, '-') << "\n";
std::cout << std::format("{:<20} {:>5} {:>8.1f}\n", "Wonderwall", 1995, 9.5);
std::cout << std::format("{:<20} {:>5} {:>8.1f}\n", "Jumper", 1997, 9.8);
std::cout << std::format("{:<20} {:>5} {:>8.1f}\n", "Say My Name",1999, 8.7);
}Output:
Song Year Score
-----------------------------------
Wonderwall 1995 9.5
Jumper 1997 9.8
Say My Name 1999 8.7Have the class predict the output before running.
9. Wrap-up Quiz (5 min)
Q1. What does std::format("{:>8.2f}", 3.1) produce?
A. "3.10" B. " 3.10" C. "3.1 " D. "00003.10" E. Ben got this wrong
Answer: B — width 8, right-aligned, 2 decimals.
Q2. What is wrong with this code?
std::string result = std::format("{} scored {1} points", name, score);A. Missing #include <format> B. Cannot mix implicit {} and indexed {1} C. score must be a string D. You cannot have a space inside a format string E. Ben got this wrong
Answer: B
Q3. What does std::format("{:*^20}", "Hola") produce?
A. "****Hola************" B. "********Hola********" C. "Hola****************" D. "********Hola" E. Ben got this wrong
Answer: B — center-aligned in a field of 20 with * as fill.
10. Assignment / Reading (2 min)
- Read: chapter 11 of Gorgo Starting C++ (Exceptions,
std::expected) - Do: all 9 exercises at the end of chapter 11
- Bring: any program from this term that could benefit from
std::format— we may use it as an example
Key Points to Reinforce
std::formatreturns astd::string—std::print/std::printlnwrite directly- Implicit
{}and indexed{0}cannot be mixed - Spec grammar:
[[fill]align][sign][#][0][width][.prec][type] {:.Nf}for floats,{:x}/{:o}/{:b}for bases,#for base prefix- Prefer
std::format/std::printlnover<<withstd::setw/std::setprecision