format! (și sintaxa de formatare) în Rust

Construiește un String nou din șablon și valori, cu aceeași sintaxă ca println!, dar fără să afișeze nimic.

Sintaxă
let s: String = format!("{} {}", a, b);
{}  {:?}  {:#?}          // Display, Debug, Debug pe mai multe rânduri
{:5}  {:<5}  {:^5}  {:>5}  {:*^9}   // lățime, aliniere, umplere
{:.2}  {:8.2}  {:+}      // zecimale, lățime + zecimale, semn
{:x}  {:X}  {:#x}  {:b}  {:o}  {:e}  {:05}
{nume}  {0}  {:w$}  {:.p$}

Ce face format! (și sintaxa de formatare)

format! funcționează exact ca println!, dar în loc să afișeze, returnează textul ca String. Îl folosești când ai nevoie de text compus: mesaje de eroare, nume de fișiere, rânduri pentru un raport. Toate macro-urile de afișare (println!, write!, panic!, assert! cu mesaj) folosesc această sintaxă.

În acolade: întâi ce se afișează (nimic = următorul argument, un număr = argumentul de pe acea poziție, un nume = variabila sau argumentul cu numele respectiv), apoi, după :, formatul. Formatul poate avea: un caracter de umplere urmat de aliniere (< stânga, ^ centru, > dreapta), + (afișează mereu semnul), # (forma alternativă: 0x, 0b sau Debug pe mai multe rânduri), 0 (completează cu zerouri), lățimea, .precizia și tipul (? Debug, x/X hexazecimal, b binar, o octal, e exponențial).

Lățimea și precizia pot veni din variabile: {:w$} sau {:.p$}. Numerele sunt aliniate implicit la dreapta, textul la stânga. Lățimea se măsoară în caractere, nu în octeți, deci diacriticele nu strică alinierea.

Ce returnează

Un String nou cu textul formatat.

Exemple

Exemplul 1: Construirea unui text

format! nu afișează nimic; rezultatul este păstrat în variabile și folosit mai târziu.

fn nume_fisier(an: u32, luna: u32, client: &str) -> String {
    format!("factura-{an}-{luna:02}-{}.pdf", client.to_lowercase())
}

fn main() {
    let f = nume_fisier(2026, 3, "Popescu");
    let mesaj = format!("Am generat {f} ({} caractere)", f.len());
    println!("{mesaj}");
}

Rezultat

Am generat factura-2026-03-popescu.pdf (27 caractere)

Exemplul 2: Lățime, aliniere, zecimale

Un mic raport aliniat în coloane. {:<12} aliniază textul la stânga pe 12 caractere, {:>8.2} pune numărul la dreapta, pe 8 caractere, cu două zecimale. {:-^30} centrează un titlu și umple cu cratime.

fn main() {
    let produse = [("Pâine", 2, 5.5), ("Lapte", 3, 8.99), ("Cafea", 1, 32.0)];
    println!("{:-^30}", " BON ");
    let mut total = 0.0;
    for (nume, buc, pret) in produse {
        let valoare = buc as f64 * pret;
        total += valoare;
        println!("{nume:<12}{buc:>3} x{pret:>6.2}{valoare:>8.2}");
    }
    println!("{:-<30}", "");
    println!("{:<21}{:>9.2}", "TOTAL", total);
}

Rezultat

------------ BON -------------
Pâine         2 x  5.50   11.00
Lapte         3 x  8.99   26.97
Cafea         1 x 32.00   32.00
------------------------------
TOTAL                    69.97

Exemplul 3: Numere: baze, semn, zerouri, exponent, lățime din variabilă

Aceeași valoare afișată în mai multe forme. {:02X} scrie fiecare componentă de culoare pe două cifre hexazecimale, iar {:#?} afișează o structură pe mai multe rânduri. {:>w$} ia lățimea din variabila w.

#[derive(Debug)]
struct Culoare {
    nume: &'static str,
    rgb: (u8, u8, u8),
}

fn main() {
    let n = 255;
    println!("zecimal {n}, hex {n:x}, HEX {n:X}, cu prefix {n:#x}, binar {n:#b}, octal {n:o}");
    println!("cu semn: {:+}, {:+}", 7, -7);
    println!("zerouri: {:05}, {:08.3}", 42, 3.14159);
    println!("exponent: {:e}", 1234.5);
    let w = 10;
    println!("[{:>w$}] [{:<w$}] [{:^w$}]", "dreapta", "stânga", "centru");
    let albastru = Culoare { nume: "albastru", rgb: (0, 87, 183) };
    let (r, g, b) = albastru.rgb;
    println!("{} = #{r:02X}{g:02X}{b:02X}", albastru.nume);
    println!("{:#?}", albastru);
}

Rezultat

zecimal 255, hex ff, HEX FF, cu prefix 0xff, binar 0b11111111, octal 377
cu semn: +7, -7
zerouri: 00042, 0003.142
exponent: 1.2345e3
[   dreapta] [stânga    ] [  centru  ]
albastru = #0057B7
Culoare {
    nume: "albastru",
    rgb: (
        0,
        87,
        183,
    ),
}

Greșeli frecvente

  • Folosești format! doar ca să afișezi imediat: println!("{}", format!(...)). Scrie direct println!(...); nu mai creezi un String intermediar.
  • Adaugi text în buclă cu s = format!("{s}{x}"): creezi un String nou la fiecare pas. Folosește s.push_str(...) sau write!(s, ...).
  • Aștepți ca {:.2} să rotunjească „ca la școală” orice număr. Rotunjirea se face pe valoarea binară reală: format!("{:.1}", 0.25) dă 0.2, pentru că 0.25 este reprezentat exact și se rotunjește la par.

Comenzi înrudite

  • println! și print!: Afișează text pe ieșirea standard: println! adaugă la final un rând nou, print! nu. Acoladele {} sunt înlocuite cu valori.
  • write! și writeln!: Scriu text formatat într-o destinație aleasă: un String, un fișier, stdout sau Formatter-ul din Display. Returnează un Result.
  • format_args!: Pregătește un text formatat fără să-l construiască: produce un fmt::Arguments care poate fi scris oriunde, fără alocare.
  • concat!: Lipește literali (texte, numere, bool, char) într-un singur &’static str, la compilare, fără niciun cost la rulare.