BBuzzard

An executable is a binary crate with a function named main. That function is where the program starts. println! is a macro: the ! marks it. It writes a line to stdout. eprintln! writes to stderr: use stdout for the result and stderr for diagnostics.

Every print macro takes a format string. {} uses Display (for users), {:?} uses Debug (for programmers), and {:#?} pretty-prints Debug. Names in braces capture variables: {name}. After the colon comes a spec: width, alignment, fill, precision, and radix. format! builds a String instead of printing, and write! formats into any writer.

Comments: // runs to the end of the line, /* */ can span lines, /// documents the next item, and //! documents the enclosing module. cargo doc renders the doc comments.

The smallest program, and the two output streams

fn demo_hello() {
    println!("-- hello --");

    println!("Hello, Rust");
    eprintln!("hello on stderr");
    print!("print! adds no newline, ");
    println!("so this continues the line");
}

The kinds of comments

/// Adds one. Doc comments like this one become HTML with cargo doc.
fn bump(n: i32) -> i32 {
    n + 1
}

fn demo_comments() {
    println!("-- comments --");

    // A line comment.
    let n = /* a block comment can sit inside an expression */ bump(3);
    /*
     * Block comments can span
     * several lines.
     */
    println!("bump(3) = {n}");
}

Positional, numbered, named, and captured arguments

fn demo_placeholders() {
    println!("-- placeholders --");

    let name = "Ada";
    let year = 1843;
    println!("{} wrote notes in {}", name, year);
    println!("{0} and {0} again, then {1}", name, year);
    println!("{who} in {when}", who = name, when = year);
    println!("{name} in {year}");
    println!("literal braces: {{ and }}");
}

Debug, pretty Debug, and dbg!

#[derive(Debug)]
struct Point {
    x: i32,
    y: i32,
}

#[derive(Debug)]
struct Line {
    from: Point,
    to: Point,
}

fn demo_debug() {
    println!("-- debug --");

    let p = Point { x: 3, y: 4 };
    println!("{p:?}");
    println!("{:?} {:?} {:?}", (1, "two"), [1, 2, 3], Some(5));

    let line = Line { from: Point { x: 0, y: 0 }, to: p };
    println!("{line:#?}");

    // dbg! prints file, line, and the expression to stderr, then returns the value.
    let n = dbg!(line.to.x * 2) + 1;
    println!("n {n} from y {}", line.from.y);
}

Width, alignment, and fill

fn demo_width_align() {
    println!("-- width and align --");

    println!("[{:5}] [{:<5}] [{:^5}] [{:>5}]", "ab", "ab", "ab", "ab");
    println!("[{:*^9}] [{:->6}] [{:_<6}]", "mid", 42, 7);

    let width = 8;
    println!("[{:>width$}] [{:>1$}]", "var", 6);

    for (item, price) in [("tea", 3.5), ("cake", 12.25)] {
        println!("{item:<6}|{price:>8.2}");
    }
}

Numbers: padding, precision, sign, and radix

fn demo_numbers() {
    println!("-- numbers --");

    println!("{:08} {:+} {:.2} {:.0}", 42, 5, 1.23456, 2.5);
    println!("hex {:x} {:X} {:#x} bin {:b} {:#010b} oct {:o}", 255, 255, 255, 5, 5, 8);
    println!("exp {:e} {:E}", 1234.5, 0.00012);

    let pi = std::f64::consts::PI;
    let places = 4;
    println!("pi to {places} places {pi:.places$}");
}

format! builds a String, write! appends to one

fn demo_format_to_string() {
    println!("-- format! and write! --");

    let id = format!("id={:04}", 7);
    let mut report = String::new();
    write!(report, "{id}").unwrap();

    for n in 1..=3 {
        write!(report, " [{n}]").unwrap();
    }

    writeln!(report, " done").unwrap();
    print!("{report}");
    println!("len {}", report.len());
}
$ cargo run --bin 01_print_format
-- hello --
Hello, Rust
hello on stderr
print! adds no newline, so this continues the line
-- comments --
bump(3) = 4
-- placeholders --
Ada wrote notes in 1843
Ada and Ada again, then 1843
Ada in 1843
Ada in 1843
literal braces: { and }
-- debug --
Point { x: 3, y: 4 }
(1, "two") [1, 2, 3] Some(5)
Line {
    from: Point {
        x: 0,
        y: 0,
    },
    to: Point {
        x: 3,
        y: 4,
    },
}
[01_print_format/main.rs:84:13] line.to.x * 2 = 6
n 7 from y 0
-- width and align --
[ab   ] [ab   ] [ ab  ] [   ab]
[***mid***] [----42] [7_____]
[     var] [     6]
tea   |    3.50
cake  |   12.25
-- numbers --
00000042 +5 1.23 2
hex ff FF 0xff bin 101 0b00000101 oct 10
exp 1.2345e3 1.2E-4
pi to 4 places 3.1416
-- format! and write! --
id=0007 [1] [2] [3] done
len 25

Full program

01_print_format/main.rs · 141 lines
View on GitHub
// 01. Hello, printing, and formatting
//
// An executable is a binary crate with a function named main. That function is where the
// program starts. println! is a macro: the ! marks it. It writes a line to stdout.
// eprintln! writes to stderr: use stdout for the result and stderr for diagnostics.
//
// Every print macro takes a format string. {} uses Display (for users), {:?} uses Debug
// (for programmers), and {:#?} pretty-prints Debug. Names in braces capture variables:
// {name}. After the colon comes a spec: width, alignment, fill, precision, and radix.
// format! builds a String instead of printing, and write! formats into any writer.
//
// Comments: // runs to the end of the line, /* */ can span lines, /// documents the next
// item, and //! documents the enclosing module. cargo doc renders the doc comments.
//
// Run: cargo run --bin 01_print_format

use std::fmt::Write as _;

// Example 1: the smallest program, and the two output streams.
fn demo_hello() {
    println!("-- hello --");

    println!("Hello, Rust");
    eprintln!("hello on stderr");
    print!("print! adds no newline, ");
    println!("so this continues the line");
}

/// Adds one. Doc comments like this one become HTML with cargo doc.
fn bump(n: i32) -> i32 {
    n + 1
}

// Example 2: the kinds of comments.
fn demo_comments() {
    println!("-- comments --");

    // A line comment.
    let n = /* a block comment can sit inside an expression */ bump(3);
    /*
     * Block comments can span
     * several lines.
     */
    println!("bump(3) = {n}");
}

// Example 3: positional, numbered, named, and captured arguments.
fn demo_placeholders() {
    println!("-- placeholders --");

    let name = "Ada";
    let year = 1843;
    println!("{} wrote notes in {}", name, year);
    println!("{0} and {0} again, then {1}", name, year);
    println!("{who} in {when}", who = name, when = year);
    println!("{name} in {year}");
    println!("literal braces: {{ and }}");
}

#[derive(Debug)]
struct Point {
    x: i32,
    y: i32,
}

#[derive(Debug)]
struct Line {
    from: Point,
    to: Point,
}

// Example 4: Debug, pretty Debug, and dbg!.
fn demo_debug() {
    println!("-- debug --");

    let p = Point { x: 3, y: 4 };
    println!("{p:?}");
    println!("{:?} {:?} {:?}", (1, "two"), [1, 2, 3], Some(5));

    let line = Line { from: Point { x: 0, y: 0 }, to: p };
    println!("{line:#?}");

    // dbg! prints file, line, and the expression to stderr, then returns the value.
    let n = dbg!(line.to.x * 2) + 1;
    println!("n {n} from y {}", line.from.y);
}

// Example 5: width, alignment, and fill.
fn demo_width_align() {
    println!("-- width and align --");

    println!("[{:5}] [{:<5}] [{:^5}] [{:>5}]", "ab", "ab", "ab", "ab");
    println!("[{:*^9}] [{:->6}] [{:_<6}]", "mid", 42, 7);

    let width = 8;
    println!("[{:>width$}] [{:>1$}]", "var", 6);

    for (item, price) in [("tea", 3.5), ("cake", 12.25)] {
        println!("{item:<6}|{price:>8.2}");
    }
}

// Example 6: numbers: padding, precision, sign, and radix.
fn demo_numbers() {
    println!("-- numbers --");

    println!("{:08} {:+} {:.2} {:.0}", 42, 5, 1.23456, 2.5);
    println!("hex {:x} {:X} {:#x} bin {:b} {:#010b} oct {:o}", 255, 255, 255, 5, 5, 8);
    println!("exp {:e} {:E}", 1234.5, 0.00012);

    let pi = std::f64::consts::PI;
    let places = 4;
    println!("pi to {places} places {pi:.places$}");
}

// Example 7: format! builds a String, write! appends to one.
fn demo_format_to_string() {
    println!("-- format! and write! --");

    let id = format!("id={:04}", 7);
    let mut report = String::new();
    write!(report, "{id}").unwrap();

    for n in 1..=3 {
        write!(report, " [{n}]").unwrap();
    }

    writeln!(report, " done").unwrap();
    print!("{report}");
    println!("len {}", report.len());
}

fn main() {
    demo_hello();
    demo_comments();
    demo_placeholders();
    demo_debug();
    demo_width_align();
    demo_numbers();
    demo_format_to_string();
}