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 ou String
Seção intitulada “&str ou String”&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}");}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.
Aumentando uma String
Seção intitulada “Aumentando uma 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!Juntando strings
Seção intitulada “Juntando strings”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}");}Métodos de string úteis
Seção intitulada “Métodos de string úteis”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!"}Percorrendo uma string
Seção intitulada “Percorrendo uma string”Para passar caractere por caractere, use .chars():
fn main() { for c in "abc".chars() { println!("{c}"); }}Prática
Seção intitulada “Prática”1. Limpe uma entrada bagunçada
Seção intitulada “1. Limpe uma entrada bagunçada”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 great13 bytesA ordem importa: se você chamasse .replace("fun", "great") antes de .to_lowercase(), nada seria trocado, porque o texto ainda diz FUN.
2. Monte um endereço de e-mail
Seção intitulada “2. Monte um endereço de e-mail”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&stré um texto emprestado e fixo;Stringtem dono e pode crescer.- Aumente uma
Stringcom.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
Seção intitulada “Teste o que aprendeu”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
Para saber mais
Seção intitulada “Para saber mais”- Storing UTF-8 Encoded Text with Strings — The Rust Book (em inglês): o capítulo oficial sobre
String, incluindo por que não dá para acessar por posição. - String Slices — The Rust Book (em inglês): o que um
&strrealmente é, depois que você aprender sobre borrowing. - Strings — Rust by Example (em inglês): exemplos que você pode rodar de
Stringe&str, além de caracteres de escape e raw strings. String— documentação da biblioteca padrão (em inglês): todos os métodos de umaStringcom dono, cada um com um pequeno exemplo.str— documentação da biblioteca padrão (em inglês): métodos comotrim,contains,replaceesplit, que funcionam com qualquer texto.