ChatGPT解决这个技术问题 Extra ChatGPT

How do I concatenate strings?

How do I concatenate the following combinations of types:

str and str

String and str

String and String

Note that str and &str are different types and for 99% of the time, you only should care about &str. There are other questions detailing the differences between them.
Does this answer your question? How to concatenate static strings in Rust

S
Shepmaster

When you concatenate strings, you need to allocate memory to store the result. The easiest to start with is String and &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);
}

Here, we have an owned string that we can mutate. This is efficient as it potentially allows us to reuse the memory allocation. There's a similar case for String and String, as &String can be dereferenced as &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);
}

After this, another_owned_string is untouched (note no mut qualifier). There's another variant that consumes the String but doesn't require it to be mutable. This is an implementation of the Add trait that takes a String as the left-hand side and a &str as the right-hand side:

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);
}

Note that owned_string is no longer accessible after the call to +.

What if we wanted to produce a new string, leaving both untouched? The simplest way is to use format!:

fn main() {
    let borrowed_string: &str = "hello ";
    let another_borrowed_string: &str = "world";
    
    let together = format!("{}{}", borrowed_string, another_borrowed_string);

    // After https://rust-lang.github.io/rfcs/2795-format-args-implicit-identifiers.html
    // let together = format!("{borrowed_string}{another_borrowed_string}");

    println!("{}", together);
}

Note that both input variables are immutable, so we know that they aren't touched. If we wanted to do the same thing for any combination of String, we can use the fact that String also can be formatted:

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);

    // After https://rust-lang.github.io/rfcs/2795-format-args-implicit-identifiers.html
    // let together = format!("{owned_string}{another_owned_string}");
    println!("{}", together);
}

You don't have to use format! though. You can clone one string and append the other string to the new string:

fn main() {
    let owned_string: String = "hello ".to_owned();
    let borrowed_string: &str = "world";
    
    let together = owned_string.clone() + borrowed_string;
    println!("{}", together);
}

Note - all of the type specification I did is redundant - the compiler can infer all the types in play here. I added them simply to be clear to people new to Rust, as I expect this question to be popular with that group!


What do you think about Add / + symbol? You could cover it if you want.
Maybe that's simple enough, but understanding it requires looking at the possible type signatures for Add with String.
@jsalter that's a pretty separate topic, so it may be good as another top-level question. I have updated to link to the appropriate docs (as close as I can get, at least...)
@ChrisMorgan It should be noted that the discrepancy .to_owned() and .to_string() has been fixed since the above comment thanks to impl specialization. They both now have the same performance when called on a &str. Relevant commit: github.com/rust-lang/rust/pull/32586/files
@paddyg Yes, it's kind of subtle. The starting types are both String, but then you take a reference to one (&String) which can be coerced to a &str. I put the entire path String -> &String -> &str because beginners may not even realize that you can take a reference to a String. :-)
S
Shepmaster

To concatenate multiple strings into a single string, separated by another character, there are a couple of ways.

The nicest I have seen is using the join method on an array:

fn main() {
    let a = "Hello";
    let b = "world";
    let result = [a, b].join("\n");

    print!("{}", result);
}

Depending on your use case you might also prefer more control:

fn main() {
    let a = "Hello";
    let b = "world";
    let result = format!("{}\n{}", a, b);

    print!("{}", result);
}

There are some more manual ways I have seen, some avoiding one or two allocations here and there. For readability purposes I find the above two to be sufficient.


Where is join documented? It seems to sit halfway between an Array and a String. I searched through the array documentation and was quickly confused.
@DuaneJ join is actually attached to the SliceContactExt trait. The trait is marked unstable but its methods are stable and are included in the Prelude so they're usable everywhere by default. The team appear to be well aware this trait does not need to exist and I imagine things will change in future with it.
Perhaps you should mention that join is more efficient than s1.to_owned().push_str(s2) for concatenating two str's as it avoids the second allocation.
M
Matthias Braun

Simple ways to concatenate strings in Rust

There are various methods available in Rust to concatenate strings

First method (Using concat!() ):

fn main() {
    println!("{}", concat!("a", "b"))
}

The output of the above code is :

ab

Second method (using push_str() and + 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 + &_c);
}

The output of the above code is:

ab abc

Third method (Using format!()):

fn main() {
    let mut _a = "a".to_string();
    let _b = "b".to_string();
    let _c = format!("{}{}", _a, _b);

    println!("{}", _c);
}

The output of the above code is :

ab

Check it out and experiment with Rust playground.


This answer does not add anything new to the existing answers.
The answer is nicely formatted, which serves a purpose. It may not add anything new, but I'm glad @ashwin-rajeev boiled it down.
concat only works with literals, so, not super useful.
s
suside

I think that concat method and + should be mentioned here as well:

assert_eq!(
  ("My".to_owned() + " " + "string"),
  ["My", " ", "string"].concat()
);

and there is also concat! macro but only for literals:

let s = concat!("test", 10, 'b', true);
assert_eq!(s, "test10btrue");

+ is already mentioned in an existing answer. (This is an implementation of the Add trait that takes a String as the left-hand side and a &str as the right-hand side:)
True, existing answer is so broad I didn't notice though.
Best answer so far. Just use array method or concat for strings. Macros are just handy for hiding some syntax rather than inventing complex syntax making core language cryptic. Add trait could be nice for objects but can be confusing at least.
J
JamesHoux

Concatenation by String Interpolation

UPDATE: As of 2021, Dec 28, this is available in Rust 1.58 Beta. You no longer need Rust Nightly build to do String Interpolation. (Leaving remainder of answer unchanged for posterity).

RFC 2795 issued 2019-10-27: Suggests support for implicit arguments to do what many people would know as "string interpolation" -- a way of embedding arguments within a string to concatenate them.

RFC: https://rust-lang.github.io/rfcs/2795-format-args-implicit-identifiers.html

Latest issue status can be found here: https://github.com/rust-lang/rust/issues/67984

At the time of this writing (2020-9-24), I believe this feature should be available in the Rust Nightly build.

This will allow you to concatenate via the following shorthand:

format_args!("hello {person}")

It is equivalent to this:

format_args!("hello {person}", person=person)

There is also the "ifmt" crate, which provides its own kind of string interpolation:

https://crates.io/crates/ifmt


Now this is available in Rust 1.58 Beta.
a
at54321

As of Rust 1.58, you can also concatenate two or more variables like this: format!("{a}{b}{c}"). That's basically the same as format!("{}{}{}", a, b, c), but a bit shorter and (arguably) easier to read. Those variables can be String, &str (and also other non-string types for that matter). The result is a String. See this for more.


M
Murugaraju Perumalla

By Default in Rust is all about MemoryManage and Owenership and Move, we dont see usually like copy or deep copy hence if you are trying to concatinate strings then left hand side should type String which is growable and should be mutable type, the right hand side can be normal string literal a.k.a type String slices

    fn main (){
            let mut x = String::from("Hello"); // type String
            let y = "World" // type &str
            println!("data printing -------> {}",x+y);



}

https://i.stack.imgur.com/h6WQI.png


P
Pkzoid Token
fn main() {
    let a = String::from("Name");
    let b = "Pkgamer";
    println!("{}",a+b)
}

In case you're wondering why you're getting downvoted: You're not providing any explanatory text, your answer doesn't address the question fully (what about the three combinations of &str/String?), and your answer doesn't add much over e.g. this one.