Formatar Strings em Rust
Rust oferece um sistema de formatação poderoso e seguro em tempo de compilação. As macros format!(), println!() e write!() usam a mesma sintaxe e cobrem praticamente qualquer necessidade de formatação de texto.
Formatação básica com format!() e println!()
A macro format!() retorna uma String formatada. println!() imprime direto no terminal:
fn main() {
let nome = "Maria";
let idade = 28;
// println! imprime no terminal
println!("Nome: {}, Idade: {}", nome, idade);
// format! retorna uma String
let msg = format!("Olá, {}! Você tem {} anos.", nome, idade);
println!("{}", msg);
// Posição dos argumentos
println!("{0} tem {1} anos. {0} programa em Rust.", nome, idade);
// Argumentos nomeados
println!(
"{nome} está aprendendo {linguagem}",
nome = "João",
linguagem = "Rust"
);
// Variáveis capturadas (Rust 1.58+)
let linguagem = "Rust";
println!("{nome} programa em {linguagem}");
}
Saída:
Nome: Maria, Idade: 28
Olá, Maria! Você tem 28 anos.
Maria tem 28 anos. Maria programa em Rust.
João está aprendendo Rust
Maria programa em Rust
Padding e alinhamento
Controle a largura e o alinhamento do texto com especificadores de formato:
fn main() {
// Largura mínima (alinhado à direita por padrão)
println!("[{:>10}]", "Rust"); // direita
println!("[{:<10}]", "Rust"); // esquerda
println!("[{:^10}]", "Rust"); // centro
// Caractere de preenchimento personalizado
println!("[{:*>10}]", "Rust"); // preenche com *
println!("[{:-<10}]", "Rust"); // preenche com -
println!("[{:.^10}]", "Rust"); // preenche com .
// Números com zeros à esquerda
println!("Código: {:05}", 42);
println!("Binário: {:08b}", 42);
// Tabela formatada
println!("{:<15} {:>8} {:>10}", "Produto", "Qtd", "Preço");
println!("{:<15} {:>8} {:>10.2}", "Notebook", 3, 4599.90);
println!("{:<15} {:>8} {:>10.2}", "Mouse", 15, 89.99);
println!("{:<15} {:>8} {:>10.2}", "Teclado", 8, 249.50);
}
Saída:
[ Rust]
[Rust ]
[ Rust ]
[******Rust]
[Rust------]
[...Rust...]
Código: 00042
Binário: 00101010
Produto Qtd Preço
Notebook 3 4599.90
Mouse 15 89.99
Teclado 8 249.50
Precisão decimal e formatos numéricos
Controle a precisão de números decimais e use diferentes bases numéricas:
fn main() {
let pi = std::f64::consts::PI;
// Precisão decimal
println!("Pi padrão: {}", pi);
println!("2 decimais: {:.2}", pi);
println!("5 decimais: {:.5}", pi);
println!("0 decimais: {:.0}", pi);
// Notação científica
println!("Científica: {:e}", 1_500_000.0_f64);
println!("Científica: {:E}", 0.00015_f64);
// Bases numéricas
let valor = 255_u32;
println!("Decimal: {}", valor);
println!("Binário: {:b}", valor);
println!("Octal: {:o}", valor);
println!("Hexadecimal: {:x}", valor);
println!("Hex maiúsc: {:X}", valor);
// Com prefixo de base
println!("Com prefixo: {:#b}", valor);
println!("Com prefixo: {:#o}", valor);
println!("Com prefixo: {:#x}", valor);
// Largura dinâmica
let largura = 20;
println!("{:>largura$.2}", pi, largura = largura);
}
Saída:
Pi padrão: 3.141592653589793
2 decimais: 3.14
5 decimais: 3.14159
0 decimais: 3
Científica: 1.5e6
Científica: 1.5E-4
Decimal: 255
Binário: 11111111
Octal: 377
Hexadecimal: ff
Hex maiúsc: FF
Com prefixo: 0b11111111
Com prefixo: 0o377
Com prefixo: 0xff
3.14
Usando write!() e writeln!()
A macro write!() escreve em qualquer tipo que implemente std::fmt::Write (strings) ou std::io::Write (arquivos, buffers):
use std::fmt::Write as FmtWrite;
use std::io::Write as IoWrite;
fn main() {
// write! em String
let mut texto = String::new();
write!(texto, "Soma: {}", 2 + 3).unwrap();
writeln!(texto, " (calculado)").unwrap();
writeln!(texto, "Produto: {}", 2 * 3).unwrap();
println!("{}", texto);
// write! em Vec<u8> (buffer de bytes)
let mut buffer: Vec<u8> = Vec::new();
writeln!(buffer, "Linha 1: {}", "dados").unwrap();
writeln!(buffer, "Linha 2: {:.2}", 3.14159).unwrap();
let resultado = String::from_utf8(buffer).unwrap();
println!("{}", resultado);
}
Saída:
Soma: 5 (calculado)
Produto: 6
Linha 1: dados
Linha 2: 3.14
Implementando Display para tipos personalizados
Para usar seus tipos com format!(), implemente o trait std::fmt::Display:
use std::fmt;
struct Moeda {
simbolo: &'static str,
valor: f64,
}
impl fmt::Display for Moeda {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{} {:.2}", self.simbolo, self.valor)
}
}
fn main() {
let preco = Moeda { simbolo: "R$", valor: 1499.90 };
println!("Preço: {}", preco);
println!("Debug: {:?}", format!("{}", preco));
// Funciona com format! também
let mensagem = format!("Total: {}", preco);
println!("{}", mensagem);
}
Saída:
Preço: R$ 1499.90
Debug: "R$ 1499.90"
Total: R$ 1499.90
Referência rápida de especificadores
| Especificador | Descrição | Exemplo |
|---|---|---|
{} | Display padrão | println!("{}", 42) |
{:?} | Debug | println!("{:?}", vec![1,2]) |
{:#?} | Debug bonito | println!("{:#?}", vec![1,2]) |
{:.2} | 2 decimais | println!("{:.2}", 3.14159) |
{:>10} | Alinhado à direita | println!("{:>10}", "Rust") |
{:<10} | Alinhado à esquerda | println!("{:<10}", "Rust") |
{:^10} | Centralizado | println!("{:^10}", "Rust") |
{:05} | Zeros à esquerda | println!("{:05}", 42) |
{:b} | Binário | println!("{:b}", 10) |
{:x} | Hexadecimal | println!("{:x}", 255) |
Veja também
- Converter String para Número — parse de strings para tipos numéricos
- Dividir String em Rust — quebre strings em partes
- Escrever em Arquivo — use
write!()para gravar em arquivos - Serializar Struct para JSON — formate dados como JSON
- Ler Input do Usuário — formate mensagens de prompt
- Documentação oficial:
std::fmt