Odpowiedzi:
Podczas łączenia łańcuchów należy przydzielić pamięć, aby zapisać wynik. Najłatwiej jest zacząć String
a &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);
}
Tutaj mamy własny ciąg, który możemy mutować. Jest to wydajne, ponieważ potencjalnie pozwala nam ponownie wykorzystać przydział pamięci. Istnieje podobny przypadek String
i String
, jak &String
można wyrejestrować jako&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);
}
Po tym another_owned_string
jest nietknięty (nie ma mut
kwalifikatora). Jest jeszcze jeden wariant, który zużywaString
ale nie wymaga to być zmienny. Jest to implementacja Add
cechy, która przyjmuje String
jako lewą stronę i &str
jako prawą stronę:
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);
}
Pamiętaj, że owned_string
nie jest już dostępny po połączeniu z +
.
Co jeśli chcielibyśmy wyprodukować nowy ciąg, pozostawiając oba nietknięte? Najprostszym sposobem jest użycie format!
:
fn main() {
let borrowed_string: &str = "hello ";
let another_borrowed_string: &str = "world";
let together = format!("{}{}", borrowed_string, another_borrowed_string);
println!("{}", together);
}
Zauważ, że obie zmienne wejściowe są niezmienne, więc wiemy, że nie są dotykane. Jeśli chcielibyśmy zrobić to samo dla dowolnej kombinacji String
, możemy skorzystać z faktu, że String
można również sformatować:
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);
}
Nie musisz jednak używać format!
. Możesz sklonować jeden ciąg i dołączyć drugi do nowego:
fn main() {
let owned_string: String = "hello ".to_owned();
let borrowed_string: &str = "world";
let together = owned_string.clone() + borrowed_string;
println!("{}", together);
}
Uwaga - cała specyfikacja typu, którą zrobiłem, jest zbędna - kompilator może wnioskować o wszystkich typach tutaj odtwarzanych. Dodałem je po prostu, aby były jasne dla osób początkujących w Rust, ponieważ spodziewam się, że to pytanie będzie popularne wśród tej grupy!
Add
/ +
symbol? Możesz to pokryć, jeśli chcesz.
.to_owned()
i .to_string()
została naprawiona od powyższego komentarza dzięki specjalizacji impl. Oba mają teraz taką samą wydajność, gdy są wywoływane &str
. Odpowiednie zatwierdzanie: github.com/rust-lang/rust/pull/32586/files
Aby połączyć wiele ciągów w jeden ciąg oddzielony innym znakiem, istnieje kilka sposobów.
Najmilsze, jakie widziałem, to użycie join
metody na tablicy:
fn main() {
let a = "Hello";
let b = "world";
let result = [a, b].join("\n");
print!("{}", result);
}
W zależności od przypadku użycia możesz również preferować większą kontrolę:
fn main() {
let a = "Hello";
let b = "world";
let result = format!("{}\n{}", a, b);
print!("{}", result);
}
Widziałem kilka ręcznych sposobów, niektóre unikały jednego lub dwóch przydziałów tu i tam. Dla celów czytelności powyższe dwa są wystarczające.
join
jest właściwie przymocowany do tej SliceContactExt
cechy . Cecha jest oznaczona jako niestabilna, ale jej metody są stabilne i są uwzględnione w Preludium, dzięki czemu można je stosować wszędzie domyślnie. Zespół wydaje się być świadomy, że ta cecha nie musi istnieć i myślę, że wraz z nią wszystko się zmieni.
Myślę, że tę concat
metodę +
należy również wymienić:
assert_eq!(
("My".to_owned() + " " + "string"),
["My", " ", "string"].concat()
);
i jest też concat!
makro, ale tylko dla literałów:
let s = concat!("test", 10, 'b', true);
assert_eq!(s, "test10btrue");
+
jest już wspomniany w istniejącej odpowiedzi . ( Jest to realizacja Add
cecha, która trwa String
jako lewej strony a &str
jak po prawej stronie: )
W RUST dostępne są różne metody łączenia łańcuchów
concat!()
):fn main() {
println!("{}", concat!("a", "b"))
}
Dane wyjściowe powyższego kodu to:
ab
push_str()
i +
operator):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);
}
Dane wyjściowe powyższego kodu to:
ab
ABC
Using format!()
):fn main() {
let mut _a = "a".to_string();
let _b = "b".to_string();
let _c = format!("{}{}", _a, _b);
println!("{}", _c);
}
Dane wyjściowe powyższego kodu to:
ab
sprawdź to i eksperymentuj z placem zabaw Rust
str
i&str
są różne rodzaje i do 99% czasu, tylko powinien dbać o&str
. Są też inne pytania wyszczególniające różnice między nimi.