Pular para o conteúdo

Strings em Rust

Trabalhar com texto é um dos primeiros lugares em que o Rust parece diferente de outras linguagens, principalmente porque ele tem dois tipos de string. Depois que você entende o motivo, a confusão passa.

  • &str (“string slice”, ou fatia de string): um texto que já existe em algum lugar, normalmente escrito direto no código. Tem tamanho fixo e não pode crescer.
  • String: um texto que pertence à variável (owned) e pode crescer. Você pode adicionar coisas a ele, e ele fica guardado no heap.
fn main() {
let literal: &str = "olá"; // um string slice
let owned: String = String::from("olá"); // uma String com dono
println!("{literal} / {owned}");
}
▶ Experimente você mesmo

Uma regra prática simples: se você só vai imprimir um texto fixo, "assim" (um &str) resolve. Se precisa montar, aumentar ou modificar o texto enquanto o programa roda, use String.

fn main() {
let mut greeting = String::from("Olá");
greeting.push_str(", mundo"); // adiciona um &str
greeting.push('!'); // adiciona um único char
println!("{greeting}");
}

Saída:

Olá, mundo!
▶ Experimente você mesmo

Você pode juntar strings com + ou usar format! (que normalmente é a opção mais clara):

fn main() {
let first = String::from("Olá, ");
let second = String::from("mundo!");
let combined = first + &second; // repare no & antes de second
println!("{combined}");
// format! costuma ser mais fácil de ler:
let name = "Ferris";
let greeting = format!("Olá, {name}!");
println!("{greeting}");
}
▶ Experimente você mesmo

Alguns que você vai usar o tempo todo. Neste exemplo, o texto fica em inglês de propósito: o .len() mede o tamanho em bytes, e letras acentuadas como “á” ocupam 2 bytes em UTF-8, então o resultado mudaria.

fn main() {
let text = " Hello, Rust! ";
println!("{}", text.trim()); // "Hello, Rust!" (sem espaços nas pontas)
println!("{}", text.to_uppercase()); // " HELLO, RUST! "
println!("{}", text.to_lowercase()); // " hello, rust! "
println!("{}", text.contains("Rust")); // true
println!("{}", text.trim().len()); // 12 (tamanho em bytes)
println!("{}", text.trim().replace("Rust", "World")); // "Hello, World!"
}
▶ Experimente você mesmo

Para passar caractere por caractere, use .chars():

fn main() {
for c in "abc".chars() {
println!("{c}");
}
}
▶ Experimente você mesmo

Alguém digitou " rUsT is FUN " em um formulário. Transforme isso em rust is great: tire os espaços sobrando, deixe tudo em minúsculas e troque fun por great. Depois imprima o resultado e o tamanho dele. Dica: os métodos de string podem ser encadeados, um depois do outro: text.trim().to_lowercase()....

Aqui o texto fica em inglês de propósito: o programa imprime o tamanho em bytes, e letras acentuadas ocupam 2 bytes em UTF-8, o que mudaria o resultado.

Ver solução
fn main() {
let input = " rUsT is FUN ";
// primeiro trim, depois minúsculas, depois troca "fun" (já em minúsculas)
let clean = input.trim().to_lowercase().replace("fun", "great");
println!("{clean}");
println!("{} bytes", clean.len());
}

Saída:

rust is great
13 bytes
▶ Experimente você mesmo

A ordem importa: se você chamasse .replace("fun", "great") antes de .to_lowercase(), nada seria trocado, porque o texto ainda diz FUN.

Dados first = "Ada" e last = "Lovelace", monte a String [email protected] e imprima. Depois imprima se ela contém um @. Dica: o format! aceita expressões como first.to_lowercase() como argumentos para os seus marcadores {}.

Ver solução
fn main() {
let first = "Ada";
let last = "Lovelace";
let email = format!("{}.{}@example.com", first.to_lowercase(), last.to_lowercase());
println!("{email}");
println!("parece válido: {}", email.contains('@'));
}

Saída:

parece válido: true
▶ Experimente você mesmo
  • &str é um texto emprestado e fixo; String tem dono e pode crescer.
  • Aumente uma String com .push_str() (para texto) ou .push() (para um único caractere).
  • Prefira format! a + para juntar strings: é mais claro e não move nada.
  • Métodos comuns: .trim(), .to_uppercase(), .contains(), .replace(), .chars().

Teste o que aprendeu

1. Qual tipo de string tem dono e pode crescer enquanto o programa roda?

2. Por que esta página prefere format! a + para juntar mais de duas strings?

3. Por que não dá para acessar uma string do Rust com text[0]?

4. Qual método adiciona um único caractere a uma String, como em greeting.push('!')?

Pontuação: 0 / 4