Risposte:
Quando si concatenano le stringhe, è necessario allocare memoria per archiviare il risultato. Il più semplice per iniziare è String
e &str
:
fn main() {
let mut owned_string: String = "hello ".to_owned();
let borrowed_string: &str = "world";
owned_string.push_str(borrowed_string);
println!("{}", owned_string);
}
Qui, abbiamo una stringa di proprietà che possiamo mutare. Questo è efficiente poiché potenzialmente ci consente di riutilizzare l'allocazione di memoria. C'è un caso simile per String
e String
, come &String
può essere indicato come&str
.
fn main() {
let mut owned_string: String = "hello ".to_owned();
let another_owned_string: String = "world".to_owned();
owned_string.push_str(&another_owned_string);
println!("{}", owned_string);
}
Dopo questo, another_owned_string
non viene toccato (non notare alcun mut
qualificatore). C'è un'altra variante che consuma il String
ma non richiede che sia mutabile. Questa è un'implementazione del Add
tratto che prende a String
come lato sinistro e a &str
come lato destro:
fn main() {
let owned_string: String = "hello ".to_owned();
let borrowed_string: &str = "world";
let new_owned_string = owned_string + borrowed_string;
println!("{}", new_owned_string);
}
Si noti che owned_string
non è più accessibile dopo la chiamata a +
.
E se volessimo produrre una nuova stringa, lasciando intatti entrambi? Il modo più semplice è usare format!
:
fn main() {
let borrowed_string: &str = "hello ";
let another_borrowed_string: &str = "world";
let together = format!("{}{}", borrowed_string, another_borrowed_string);
println!("{}", together);
}
Nota che entrambe le variabili di input sono immutabili, quindi sappiamo che non vengono toccate. Se volessimo fare la stessa cosa per qualsiasi combinazione di String
, possiamo usare il fatto che String
può anche essere formattato:
fn main() {
let owned_string: String = "hello ".to_owned();
let another_owned_string: String = "world".to_owned();
let together = format!("{}{}", owned_string, another_owned_string);
println!("{}", together);
}
Non è necessario usare format!
comunque. Puoi clonare una stringa e aggiungere l'altra stringa alla nuova stringa:
fn main() {
let owned_string: String = "hello ".to_owned();
let borrowed_string: &str = "world";
let together = owned_string.clone() + borrowed_string;
println!("{}", together);
}
Nota : tutte le specifiche di tipo che ho fatto sono ridondanti: il compilatore può inferire tutti i tipi in gioco qui. Li ho aggiunti semplicemente per essere chiari alle persone che non conoscono Rust, poiché mi aspetto che questa domanda sia popolare con quel gruppo!
Add
/ +
simbolo? Potresti coprirlo se vuoi.
.to_owned()
ed .to_string()
è stato fissato dal commento di cui sopra grazie alla specializzazione impl. Entrambi hanno ora le stesse prestazioni quando vengono chiamati a &str
. Impegno pertinente: github.com/rust-lang/rust/pull/32586/files
Per concatenare più stringhe in una singola stringa, separate da un altro carattere, ci sono un paio di modi.
Il più bello che abbia mai visto è usare il join
metodo su un array:
fn main() {
let a = "Hello";
let b = "world";
let result = [a, b].join("\n");
print!("{}", result);
}
A seconda del tuo caso d'uso potresti anche preferire un maggiore controllo:
fn main() {
let a = "Hello";
let b = "world";
let result = format!("{}\n{}", a, b);
print!("{}", result);
}
Ci sono altri modi manuali che ho visto, alcuni che evitano una o due allocazioni qua e là. Ai fini della leggibilità trovo che i due precedenti siano sufficienti.
join
documentato? Sembra stare a metà strada tra una matrice e una stringa. Ho cercato nella documentazione dell'array e sono stato rapidamente confuso.
join
è effettivamente collegato al il SliceContactExt
tratto . Il tratto è contrassegnato come instabile ma i suoi metodi sono stabili e sono inclusi nel Preludio, quindi sono utilizzabili ovunque per impostazione predefinita. Il team sembra essere ben consapevole che questo tratto non ha bisogno di esistere e immagino che le cose cambieranno in futuro con esso.
Penso che questo concat
metodo +
debba essere menzionato anche qui:
assert_eq!(
("My".to_owned() + " " + "string"),
["My", " ", "string"].concat()
);
e c'è anche concat!
macro ma solo per i letterali:
let s = concat!("test", 10, 'b', true);
assert_eq!(s, "test10btrue");
+
è già menzionato in una risposta esistente . ( Questa è un'implementazione del Add
tratto che prende una String
come il lato sinistro e una &str
come il lato destro: )
Esistono vari metodi disponibili in RUST per concatenare le stringhe
concat!()
):fn main() {
println!("{}", concat!("a", "b"))
}
L'output del codice sopra è:
ab
push_str()
e +
operatore):fn main() {
let mut _a = "a".to_string();
let _b = "b".to_string();
let _c = "c".to_string();
_a.push_str(&_b);
println!("{}", _a);
println!("{}", _a + &_b);
}
L'output del codice sopra è:
ab
abc
Using format!()
):fn main() {
let mut _a = "a".to_string();
let _b = "b".to_string();
let _c = format!("{}{}", _a, _b);
println!("{}", _c);
}
L'output del codice sopra è:
ab
dai un'occhiata e sperimenta il terreno di gioco Rust
str
e&str
sono tipi diversi e per il 99% delle volte, dovresti solo preoccupartene&str
. Ci sono altre domande che descrivono in dettaglio le differenze tra loro.