【问题标题】:Rust String concatenation [duplicate]Rust 字符串连接 [重复]
【发布时间】:2015-08-23 05:01:44
【问题描述】:

我本周开始使用 Rust 编程,但在理解字符串的工作原理时遇到了很多问题。

现在,我正在尝试做一个简单的程序,打印一个附加订单的玩家列表(仅用于学习目的)。

let res : String = pl.name.chars().enumerate().fold(String::new(),|res,(i,ch)| -> String {
    res+=format!("{} {}\n",i.to_string(),ch.to_string());
});

println!("{}", res);

这是我的想法,我知道我可以只使用 for 循环,但目标是了解不同的迭代器函数。

所以,我的问题是字符串连接不起作用。

   Compiling prueba2 v0.1.0 (file:///home/pancho111203/projects/prueba2)
src/main.rs:27:13: 27:16 error: binary assignment operation `+=` cannot be applied to types `collections::string::String` and `collections::string::String` [E0368]
src/main.rs:27             res+=format!("{} {}\n",i.to_string(),ch.to_string());
                           ^~~
error: aborting due to previous error
Could not compile `prueba2`.

我尝试使用 &str,但无法从 ich 值创建它们。

【问题讨论】:

  • 这可能不是真正的重复,但正如所问的那样,它似乎是一样的。随时更新您的标题和问题,以更好地反映为什么它不是重复的,我们可以取消标记它。

标签: string rust


【解决方案1】:

首先,在 Rust 中,x += y 是不可重载的,所以 += 运算符除了基本的数字类型外,不能用于任何东西。但是,即使它适用于字符串,它也将等同于 x = x + y,如下所示:

res = res + format!("{} {}\n",i.to_string(),ch.to_string())

即使类型系统允许这样做(不是因为 String + String“过载”在 Rust 中没有定义),这仍然不是 fold() 的操作方式。你想要这个:

res + &format!("{} {}\n", i, ch)

或者,作为一个可编译的示例,

fn main(){
    let x = "hello";
    let res : String = x.chars().enumerate().fold(String::new(), |res, (i, ch)| {
        res + &format!("{} {}\n", i, ch)
    });

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

当您执行折叠时,您不会重新分配累加器变量,您需要返回新值以供下一次迭代使用,这正是 res + format!(...) 所做的。

请注意,我删除了 to_string() 调用,因为它们完全没有必要 - 事实上,x.to_string() 等同于 format!("{}", x),因此您只在此处执行不必要的分配。

此外,我将 format!() 结果作为参考:&format!(...)。这是必要的,因为字符串的+“重载”是为String + &str类型对定义的,因此您需要将Stringformat!()的结果)转换为&str,这可以简单地完成通过在此处使用 &(因为 deref 强制)。

事实上,以下方式会更高效:

use std::fmt::Write;

fn main(){
    let x = "hello";
    let res: String = x.chars().enumerate().fold(String::new(), |mut res, (i, ch)| {
        write!(&mut res, "{} {}\n", i, ch).unwrap();
        res
    });

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

可以更习惯地写成

use std::fmt::Write;

fn main(){
    let x = "hello";

    let mut res = String::new(); 
    for (i, ch) in x.chars().enumerate() {
        write!(&mut res, "{} {}\n", i, ch).unwrap();
    }

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

(试试playpen

这种方式不会创建额外的分配(即来自format!() 的新字符串)。我们只是用新数据填充字符串,例如,与 Java 中的 StringBuilder 的工作方式非常相似。此处需要use std::fmt::Write 以允许在&mut String 上调用write!()

我还建议阅读官方 Rust 书籍中的the chapter on strings(如果您是 Rust 新手,请阅读整本书)。它解释了 String&str 是什么,它们有何不同以及如何有效地使用它们。

【讨论】:

  • "x += y 等价于(在运算符重载方面)x = x + y" → 我认为+= 根本无法重载。
  • 我认为 Veedrac 是对的
  • 我的立场是正确的,谢谢。
  • 自最初提出此问题以来已添加重载 +=。
猜你喜欢
  • 1970-01-01
  • 2017-04-10
  • 2020-12-30
  • 2015-07-31
  • 2013-07-21
  • 1970-01-01
  • 2013-09-14
  • 2013-11-30
  • 2013-09-26
相关资源
最近更新 更多