Rust è un linguaggio di programmazione moderno che combina prestazioni elevate con sicurezza della memoria. Uno degli aspetti più importanti di Rust è la gestione delle stringhe, che può sembrare complessa all’inizio ma offre grande flessibilità e controllo. In questo articolo, esploreremo come funzionano le stringhe in Rust, come si dichiarano, come si manipolano e alcune delle loro caratteristiche uniche.
1. Tipi di Stringhe in Rust
In Rust, ci sono due tipi principali di stringhe:
- String: Una stringa dinamica, mutabile e allocata sull’heap.
- &str: Una “string slice”, immutabile e di solito un riferimento a una porzione di una stringa esistente.
1.1. Il Tipo String
Il tipo String
è una stringa dinamica che può crescere o ridursi durante l’esecuzione del programma. È allocata sull’heap, il che significa che può contenere una quantità variabile di dati.
Dichiarazione e Inizializzazione
Per creare una nuova String
, si può usare il metodo String::new()
o la macro to_string()
:
let mut s = String::new(); // Crea una nuova stringa vuota
let s = "hello".to_string(); // Converte una stringa letterale in una String
Aggiunta di Contenuto
È possibile aggiungere contenuto a una String
utilizzando il metodo push_str
o push
:
s.push_str(" world"); // Aggiunge una stringa slice
s.push('!'); // Aggiunge un singolo carattere
Concatenazione
Per concatenare stringhe, si può usare l’operatore +
o la macro format!
:
let s1 = String::from("Hello");
let s2 = String::from(" world");
let s3 = s1 + &s2; // Nota: s1 viene consumato, s2 viene preso come riferimento
let s4 = format!("{}{}", s2, s3); // Crea una nuova stringa senza consumare s2 e s3
1.2. Il Tipo &str
Il tipo &str
è una “string slice”, ovvero un riferimento immutabile a una porzione di una stringa. È spesso utilizzato per riferirsi a parti di una String
o a stringhe letterali.
Dichiarazione e Utilizzo
Le stringhe letterali in Rust sono di tipo &str
:
let s: &str = "hello"; // s è una stringa slice
È anche possibile creare una slice da una String
:
let s1 = String::from("hello world");
let s2: &str = &s1[0..5]; // s2 è una slice che contiene "hello"
Iterazione su una Slice
Le stringhe in Rust sono codificate in UTF-8, quindi è possibile iterare sui caratteri di una stringa slice:
for c in s2.chars() {
println!("{}", c);
}
2. Operazioni Comuni sulle Stringhe
Rust fornisce una serie di metodi utili per manipolare le stringhe. Ecco alcune operazioni comuni:
2.1. Lunghezza di una Stringa
Per ottenere la lunghezza di una stringa, si usa il metodo len
:
let len = s2.len(); // Restituisce la lunghezza in byte
2.2. Accesso ai Caratteri
Per accedere ai caratteri di una stringa, si può usare il metodo chars
:
let primo_carattere = s2.chars().nth(0); // Restituisce il primo carattere come Option<char>
2.3. Sostituzione di Sottostringhe
Per sostituire una sottostringa, si usa il metodo replace
:
let nuova_stringa = s2.replace("hello", "ciao"); // Sostituisce "hello" con "ciao"
2.4. Divisione di una Stringa
Per dividere una stringa in parti, si usa il metodo split
:
let parti: Vec<&str> = s2.split(' ').collect(); // Divide la stringa in base agli spazi
3. Gestione degli Errori con le Stringhe
In Rust, le operazioni sulle stringhe possono fallire, specialmente quando si lavora con indici o caratteri non validi. È importante gestire questi errori in modo sicuro.
3.1. Accesso Sicuro agli Indici
Per accedere a un carattere in modo sicuro, si può usare il metodo get
:
if let Some(c) = s2.get(0..1) {
println!("{}", c); // Stampa il primo carattere
}
3.2. Gestione dei Caratteri Non Validi
Rust è molto attento alla gestione dei caratteri non validi in UTF-8. Se si tenta di accedere a un indice non valido, il programma potrebbe andare in panic. È sempre meglio usare metodi sicuri come chars
o get
.
4. Conclusioni
Le stringhe in Rust sono potenti e flessibili, ma richiedono una buona comprensione dei loro due tipi principali: String
e &str
. Con questa guida, hai ora una solida base per lavorare con le stringhe in Rust, dalla dichiarazione alla manipolazione avanzata. Ricorda sempre di gestire gli errori in modo sicuro e di sfruttare i metodi forniti da Rust per lavorare in modo efficiente con i dati testuali.