Stringhe in Rust
La gestione del testo è uno dei primi punti in cui Rust sembra diverso dagli altri linguaggi, soprattutto perché ha due tipi di stringa. Una volta capito il perché, smette di confondere.
&str contro String
Sezione intitolata “&str contro String”&str(«string slice», slice di stringa): testo che esiste già da qualche parte, di solito scritto direttamente nel codice. Ha dimensione fissa, non può crescere.String: un testo posseduto, che può crescere. Puoi aggiungerci cose, e vive sull’heap.
fn main() { let literal: &str = "ciao"; // una slice di stringa let owned: String = String::from("ciao"); // una String posseduta
println!("{literal} / {owned}");}Una regola pratica semplice: se stampi solo testo fisso, "così" (un &str) va benissimo. Se devi costruire, allungare o modificare del testo durante l’esecuzione, usa String.
Far crescere una String
Sezione intitolata “Far crescere una String”fn main() { let mut greeting = String::from("Ciao"); greeting.push_str(", mondo"); // aggiunge un &str greeting.push('!'); // aggiunge un singolo char
println!("{greeting}");}Output:
Ciao, mondo!Unire le stringhe
Sezione intitolata “Unire le stringhe”Puoi unire le stringhe con +, oppure usare format! (che di solito è l’opzione più chiara):
fn main() { let first = String::from("Ciao, "); let second = String::from("mondo!");
let combined = first + &second; // nota la & prima di second println!("{combined}");
// format! spesso si legge meglio: let name = "Ferris"; let greeting = format!("Ciao, {name}!"); println!("{greeting}");}Metodi utili sulle stringhe
Sezione intitolata “Metodi utili sulle stringhe”Una manciata di metodi che userai di continuo:
fn main() { let text = " Ciao, Rust! ";
println!("{}", text.trim()); // "Ciao, Rust!" (senza spazi ai lati) println!("{}", text.to_uppercase()); // " CIAO, RUST! " println!("{}", text.to_lowercase()); // " ciao, rust! " println!("{}", text.contains("Rust")); // true println!("{}", text.trim().len()); // 11 (lunghezza in byte) println!("{}", text.trim().replace("Rust", "mondo")); // "Ciao, mondo!"}Scorrere una stringa
Sezione intitolata “Scorrere una stringa”Per andare carattere per carattere, usa .chars():
fn main() { for c in "abc".chars() { println!("{c}"); }}Pratica
Sezione intitolata “Pratica”1. Ripulisci un input disordinato
Sezione intitolata “1. Ripulisci un input disordinato”Qualcuno ha scritto " rUsT mi PIACE " in un modulo. Trasformalo in rust mi diverte: togli gli spazi in più, rendi tutto minuscolo e sostituisci piace con diverte. Poi stampa il risultato e la sua lunghezza. Suggerimento: i metodi delle stringhe si possono concatenare, uno dopo l’altro: text.trim().to_lowercase()....
Mostra la soluzione
fn main() { let input = " rUsT mi PIACE ";
// prima trim, poi minuscolo, poi sostituisci "piace" (ora minuscolo) let clean = input.trim().to_lowercase().replace("piace", "diverte");
println!("{clean}"); println!("{} byte", clean.len());}Output:
rust mi diverte15 byteL’ordine conta: se chiamassi .replace("piace", "diverte") prima di .to_lowercase(), non verrebbe sostituito niente, perché il testo direbbe ancora PIACE. (Qui abbiamo evitato le lettere accentate apposta: occupano 2 byte ciascuna e cambierebbero il risultato di .len().)
2. Costruisci un indirizzo email
Sezione intitolata “2. Costruisci un indirizzo email”Dati first = "Ada" e last = "Lovelace", costruisci la String [email protected] e stampala. Poi stampa se contiene una @. Suggerimento: format! può ricevere come argomenti per i suoi segnaposto {} espressioni come first.to_lowercase().
Mostra la soluzione
fn main() { let first = "Ada"; let last = "Lovelace";
let email = format!("{}.{}@example.com", first.to_lowercase(), last.to_lowercase());
println!("{email}"); println!("sembra valida: {}", email.contains('@'));}Output:
sembra valida: trueRiepilogo
Sezione intitolata “Riepilogo”&strè testo fisso preso in prestito;Stringè posseduta e può crescere.- Fai crescere una
Stringcon.push_str()(per del testo) o.push()(per un singolo carattere). - Per unire le stringhe preferisci
format!a+: è più chiaro e non sposta niente. - Metodi comuni:
.trim(),.to_uppercase(),.contains(),.replace(),.chars().
Verifica veloce
Sezione intitolata “Verifica veloce”Verifica veloce
1. Quale tipo di stringa è posseduto e può crescere durante l'esecuzione?
2. Perché questa pagina preferisce format! a + quando si uniscono più di una o due stringhe?
3. Perché non puoi indicizzare una stringa Rust come text[0]?
4. Quale metodo aggiunge un singolo carattere a una String, come greeting.push('!')?
Punteggio: 0 / 4
Per approfondire
Sezione intitolata “Per approfondire”- Storing UTF-8 Encoded Text with Strings — The Rust Book (in inglese): il capitolo ufficiale su
String, compreso il perché non puoi indicizzare per posizione. - String Slices — The Rust Book (in inglese): cos’è davvero un
&str, una volta imparato il prestito (borrowing). - Strings — Rust by Example (in inglese): esempi eseguibili di
Stringe&str, più caratteri di escape e stringhe raw. String— documentazione della libreria standard (in inglese): tutti i metodi di unaStringposseduta, ciascuno con un piccolo esempio.str— documentazione della libreria standard (in inglese): metodi cometrim,contains,replaceesplitche funzionano su qualsiasi testo.