Réponses:
Lorsque vous concaténez des chaînes, vous devez allouer de la mémoire pour stocker le résultat. Le plus simple pour commencer est String
et &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);
}
Ici, nous avons une chaîne possédée que nous pouvons muter. Ceci est efficace car cela nous permet potentiellement de réutiliser l'allocation de mémoire. Il existe un cas similaire pour String
et String
, comme cela &String
peut être déréférencé comme&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);
}
Après cela, another_owned_string
n'est pas touché (notez pas de mut
qualificatif). Il existe une autre variante qui consomme le String
mais ne nécessite pas qu'il soit modifiable. Il s'agit d'une implémentation du Add
trait qui prend a String
comme côté gauche et a &str
comme côté droit:
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);
}
Notez que ce owned_string
n'est plus accessible après l'appel à +
.
Et si nous voulions produire une nouvelle chaîne en laissant les deux intactes? Le moyen le plus simple est d'utiliser format!
:
fn main() {
let borrowed_string: &str = "hello ";
let another_borrowed_string: &str = "world";
let together = format!("{}{}", borrowed_string, another_borrowed_string);
println!("{}", together);
}
Notez que les deux variables d'entrée sont immuables, nous savons donc qu'elles ne sont pas touchées. Si nous voulions faire la même chose pour n'importe quelle combinaison de String
, nous pouvons utiliser le fait qui String
peut également être formaté:
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);
}
Vous n'êtes pas obligé de l'utiliser format!
. Vous pouvez cloner une chaîne et ajouter l'autre chaîne à la nouvelle chaîne:
fn main() {
let owned_string: String = "hello ".to_owned();
let borrowed_string: &str = "world";
let together = owned_string.clone() + borrowed_string;
println!("{}", together);
}
Remarque - toute la spécification de type que j'ai faite est redondante - le compilateur peut déduire tous les types en jeu ici. Je les ai ajoutés simplement pour être clair pour les nouveaux utilisateurs de Rust, car je m'attends à ce que cette question soit populaire auprès de ce groupe!
Add
/ +
symbol? Vous pouvez le couvrir si vous le souhaitez.
.to_owned()
et .to_string()
a été corrigé depuis le commentaire ci-dessus grâce à la spécialisation impl. Ils ont tous deux maintenant les mêmes performances lorsqu'ils sont appelés sur un &str
. Commit pertinent: github.com/rust-lang/rust/pull/32586/files
Pour concaténer plusieurs chaînes en une seule chaîne, séparées par un autre caractère, il existe plusieurs méthodes.
Le plus beau que j'ai vu utilise la join
méthode sur un tableau:
fn main() {
let a = "Hello";
let b = "world";
let result = [a, b].join("\n");
print!("{}", result);
}
En fonction de votre cas d'utilisation, vous pouvez également préférer plus de contrôle:
fn main() {
let a = "Hello";
let b = "world";
let result = format!("{}\n{}", a, b);
print!("{}", result);
}
J'ai vu d'autres méthodes manuelles, certaines évitant une ou deux allocations ici et là. Pour des raisons de lisibilité, je trouve les deux ci-dessus suffisants.
join
est réellement attaché à la SliceContactExt
trait . Le trait est marqué comme instable mais ses méthodes sont stables et sont incluses dans le Prelude donc elles sont utilisables partout par défaut. L'équipe semble bien consciente que ce trait n'a pas besoin d'exister et j'imagine que les choses vont changer à l'avenir avec lui.
Je pense que cette concat
méthode et +
devrait être mentionnée ici aussi:
assert_eq!(
("My".to_owned() + " " + "string"),
["My", " ", "string"].concat()
);
et il y a aussi concat!
macro mais uniquement pour les littéraux:
let s = concat!("test", 10, 'b', true);
assert_eq!(s, "test10btrue");
+
est déjà mentionné dans une réponse existante . ( Ceci est une mise en œuvre du Add
trait qui prend String
comme côté gauche et &str
que la droite: )
Il existe différentes méthodes disponibles dans RUST pour concaténer des chaînes
concat!()
):fn main() {
println!("{}", concat!("a", "b"))
}
La sortie du code ci-dessus est:
un B
push_str()
et +
opérateur):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);
}
La sortie du code ci-dessus est:
un B
abc
Using format!()
):fn main() {
let mut _a = "a".to_string();
let _b = "b".to_string();
let _c = format!("{}{}", _a, _b);
println!("{}", _c);
}
La sortie du code ci-dessus est:
un B
Découvrez-le et expérimentez avec le terrain de jeu Rust
str
et&str
sont de types différents et pour 99% du temps, vous ne devriez vous en soucier que&str
. Il y a d'autres questions détaillant les différences entre elles.