如何连接字符串?

jsa*_*ter 133 string string-concatenation rust

如何连接以下类型组合:

  • strstr
  • Stringstr
  • StringString

She*_*ter 171

连接字符串时,需要分配内存来存储结果.先从最简单的是String&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);
}
Run Code Online (Sandbox Code Playgroud)

在这里,我们有一个我们可以改变的拥有字符串.这是有效的,因为它可能允许我们重用内存分配.还有一个类似的案例StringString作为&String 可提领的&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);
}
Run Code Online (Sandbox Code Playgroud)

在此之后,another_owned_string不受影响(注意没有mut限定词).还有另一个变种消耗String,但并不要求它是可变的.这是一个特征实现,Add它采用String左侧和&str右侧:

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);
}
Run Code Online (Sandbox Code Playgroud)

请注意,owned_string调用后无法再访问+.

如果我们想要生成一个新字符串,两者都保持不变,该怎么办?最简单的方法是使用format!:

fn main() {
    let borrowed_string: &str = "hello ";
    let another_borrowed_string: &str = "world";

    let together = format!("{}{}", borrowed_string, another_borrowed_string);
    println!("{}", together);
}
Run Code Online (Sandbox Code Playgroud)

请注意,两个输入变量都是不可变的,因此我们知道它们没有被触及.如果我们想为任何组合做同样的事情String,我们可以使用String也可以格式化的事实:

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);
}
Run Code Online (Sandbox Code Playgroud)

你不具备使用format!虽然.您可以克隆一个字符串并将另一个字符串附加到新字符串:

fn main() {
    let owned_string: String = "hello ".to_owned();
    let borrowed_string: &str = "world";

    let together = owned_string.clone() + borrowed_string;
    println!("{}", together);
}
Run Code Online (Sandbox Code Playgroud)

注意 - 我所做的所有类型规范都是冗余的 - 编译器可以在这里推断出所有类型.我添加它们只是为了让那些刚接触Rust的人清楚,因为我希望这个问题能够受到这个群体的欢迎!

  • @ChrisMorgan应该注意的是,自上述注释以来,由于impl特化而已经修复了`.to_owned()`和`.to_string()`的差异.当它们在`&str`上调用时,它们现在都具有相同的性能.相关提交:https://github.com/rust-lang/rust/pull/32586/files (9认同)
  • 您如何看待“添加” /“ +”符号?如果需要,可以覆盖它。 (2认同)

Sim*_*ead 38

要将多个字符串连接成一个字符串,由另一个字符分隔,有几种方法.

我见过最好的是join在数组上使用该方法:

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

    print!("{}", result);
}
Run Code Online (Sandbox Code Playgroud)

根据您的使用情况,您可能还需要更多控制:

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

    print!("{}", result);
}
Run Code Online (Sandbox Code Playgroud)

我看到了一些更多的手动方式,有些方法可以避免一两次分配.出于可读性目的,我发现上述两个就足够了.

  • @DuaneJ`adj`实际上附加到[SliceContactExt` trait](https://doc.rust-lang.org/std/slice/trait.SliceConcatExt.html).该特征被标记为不稳定,但其方法是稳定的,并且[包含在前奏中](https://doc.rust-lang.org/std/prelude/#prelude-contents),因此默认情况下它们可以在任何地方使用.团队似乎很清楚这种特性不需要存在,我想在未来事情会发生变化. (3认同)
  • 也许您应该提到“join”比“s1.to_owned().push_str(s2)”连接两个“str”更有效,因为它避免了第二次分配。 (2认同)

ASH*_*EEV 23

在 Rust 中连接字符串的简单方法

Rust 中有多种方法可以连接字符串

第一种方法(使用concat!()):

fn main() {
    println!("{}", concat!("a", "b"))
}
Run Code Online (Sandbox Code Playgroud)

上面代码的输出是:

AB


第二种方法(使用push_str()+运算符):

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);
}
Run Code Online (Sandbox Code Playgroud)

上面代码的输出是:

AB

美国广播公司


第三种方法(Using format!()):

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

    println!("{}", _c);
}
Run Code Online (Sandbox Code Playgroud)

上面代码的输出是:

AB

检查一下并尝试使用Rust playground

  • 答案的格式很好,这是有目的的。它可能不会添加任何新内容,但我很高兴@ashwin-rajeev 将其简化。 (28认同)
  • `concat` 只适用于文字,所以不是很有用。 (9认同)
  • 此答案不会为现有答案添加任何新内容。 (2认同)

sus*_*ide 17

我认为这种concat方法也+应该在这里提到:

assert_eq!(
  ("My".to_owned() + " " + "string"),
  ["My", " ", "string"].concat()
);
Run Code Online (Sandbox Code Playgroud)

还有concat!宏,但仅适用于文字:

let s = concat!("test", 10, 'b', true);
assert_eq!(s, "test10btrue");
Run Code Online (Sandbox Code Playgroud)

  • [现有答案](/sf/answers/2110835401/)中已经提到了“+”。(*这是“Add”特征的实现,它将“String”作为左侧,“&str”作为右侧:*) (2认同)
  • 确实,_现有答案_是如此广泛,但我没有注意到。 (2认同)
  • 迄今为止最好的答案。只需使用数组方法或字符串连接即可。宏只是方便地隐藏一些语法,而不是发明复杂的语法,使核心语言变得神秘。添加特征对于对象来说可能很好,但至少可能会令人困惑。 (2认同)

Jam*_*oux 8

通过字符串插值连接

RFC 2795 于 2019-10-27 发布:建议支持隐式参数来执行许多人所熟知的“字符串插值”——一种将参数嵌入字符串中以连接它们的方法。

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

最新的问题状态可以在这里找到:https : //github.com/rust-lang/rust/issues/67984

在撰写本文时(2020 年 9 月 24 日),我相信此功能应该在 Rust Nightly 版本中可用。

这将允许您通过以下速记进行连接:

format_args!("hello {person}")
Run Code Online (Sandbox Code Playgroud)

它相当于:

format_args!("hello {person}", person=person)
Run Code Online (Sandbox Code Playgroud)

还有“ifmt”包,它提供了自己的字符串插值:

https://crates.io/crates/ifmt


TSK*_*TSK 8

连接两个String

fn concat_string(a: String, b: String) -> String {
    a + &b
}
Run Code Online (Sandbox Code Playgroud)

连接两个&str

fn concat_str(a: &str, b: &str) -> String {
    a.to_string() + b
}
Run Code Online (Sandbox Code Playgroud)