如何连接字符串?


195

如何连接以下类型的组合:

  • strstr
  • Stringstr
  • StringString

13
请注意,str&str不同的类型,在99%的时间内,您只需要关心即可&str。还有其他问题详细说明了它们之间的差异。
Shepmaster 2015年

Answers:


232

连接字符串时,需要分配内存以存储结果。最简单的开始是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);
}

在这里,我们有一个可以改变的拥有的字符串。这是有效的,因为它可能使我们可以重用内存分配。还有一个类似的案例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);
}

在此之后,another_owned_string保持不变(请注意不要使用mut限定词)。还有另一个变种消耗String,但并不要求它是可变的。这是trait实现Add,将a String作为左侧,将a 作为&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);
}

请注意,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);
}

请注意,两个输入变量都是不可变的,因此我们知道它们没有被触及。如果我们想对的任何组合进行相同的操作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);
}

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

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

    let together = owned_string.clone() + borrowed_string;
    println!("{}", together);
}

注意 -我所做的所有类型说明都是多余的-编译器可以在这里推断所有正在使用的类型。我添加它们只是为了使对Rust刚接触的新手清楚,因为我希望这个问题在该小组中很受欢迎!


2
您如何看待Add/ +符号?如果需要,可以覆盖它。
bluss 2015年

也许这很简单,但是要了解它,需要查看“带字符串添加”的可能类型签名。
bluss 2015年

谢谢!您是否可以更深入地了解如何将&String取消引用为&str?它的实施的哪一部分允许这样做和/或在doco中在何处说明呢?
jsalter

1
@jsalter是一个非常独立的主题,因此它可能是另一个顶级问题。我已更新为链接到相应的文档(至少可以得到,至少...)
Shepmaster 2015年

10
@ChrisMorgan应当注意的是差异.to_owned().to_string()上述评论感谢IMPL专业化因为已定。现在,它们在调用时具有相同的性能&str。相关承诺:github.com/rust-lang/rust/pull/32586/files
乍得

49

要将多个字符串连接成一个字符串,并用另一个字符分隔,有两种方法。

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

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

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

根据您的用例,您可能还希望获得更多控制权:

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

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

我见过一些其他手动方式,有些在这里和那里避免一两个分配。出于可读性考虑,我发现以上两项已足够。


在哪里join记录?它似乎位于数组和字符串之间的中间位置。我搜索了阵列文档,并很快感到困惑。
杜安J

3
@DuaneJ join实际上附加到SliceContactExt特征上。该特征被标记为不稳定,但其方法稳定且包含在Prelude中,因此默认情况下它们可在任何地方使用。团队似乎很清楚这种特质不需要存在,我想随着它的发生,事情将会改变。
西蒙·怀特海德

9

我认为该concat方法也+应在此处提及:

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

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

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

+已在现有答案中提及。(这是一个实施Add的是需要性状的String作为左手侧和&str作为右侧:
Shepmaster

确实,现有答案如此广泛,但我没有注意到。

6

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

在RUST中可以使用多种方法来连接字符串

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

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

上面代码的输出是:

b


第二种方法(使用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 + &_b);
}

上面代码的输出是:

b

abc


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

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

上面代码的输出是:

b

检查一下并尝试使用Rust游戏场地


该答案不会在现有答案中添加任何新内容。
Shepmaster
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.