我正在尝试通过在for循环中附加到它来构建字符串。由于某种原因,字符串被移动到for循环中,我无法让它工作。我显然错过了一些东西。这是一段显示此行为的简短代码段:
fn main() {
let s = format!("some string");
for x in vec!(1,2).move_iter() {
s.append("some other string");
}
}
我从编译器(rustc 0.11.0-pre (c0a6f72 2014-06-12 14:17:13 +0000)
)收到以下错误:
test.rs:4:9: 4:10 error: use of moved value: `s`
test.rs:4 s.append("some other string");
^
test.rs:4:9: 4:10 note: `s` moved here because it has type `collections::string::String`, which is non-copyable (perhaps you meant to use clone()?)
test.rs:4 s.append("some other string");
^
error: aborting due to previous error
答案 0 :(得分:8)
更新:在最新的Rust(从1.0.0-alpha开始)append()
方法不再存在。但是,String
和Vec
都有+
方法重载,其行为与旧append()
完全相同:
let s = String::new() + "some part" + "next part";
运算符总是按值来获取操作数,因此不会导致不必要的重新分配。对于&str
,右操作数必须为String
;对于&[T]
,{1}}必须为Vec<T>
;在后一种情况下,T
必须为Clone
。
无论如何,push_str()
仍然可用。
您收到此错误的原因是您使用了错误的方法:)
String::append()
方法类似于构建器;它应该像这样使用:
let s = String::new()
.append("some part")
.append("next part");
事实上,您可以在代码中使用它:
let mut s = "some string".to_string();
for &x in [1, 2].iter() {
s = s.append("some other string"); // note the reassignment
}
这是因为append()
有此签名:
fn append(self, other: &str) -> String { ... }
也就是说,它按值接收接收器,并将其移入呼叫中。它允许轻松链接,但如果您需要修改现有变量,则有些不方便。
您正在寻找的方法称为push_str()
:
let mut s = "some string".to_string();
for &x in [1, 2].iter() {
s.push_str("some other string");
}
它只是将传递的字符串切片附加到现有的String
。请注意,您还必须将s
标记为可变。您也不需要使用vec!()
分配新的向量,静态数组就足够了。
尽管如此,如果可能的话,最好完全避免突变。 @ A.B。建议使用fold()
是绝对正确的。
答案 1 :(得分:7)
append
的功能签名是
fn append(self, second: &str) -> String
self
按值传递,这意味着如果自己实现了复制特征,它将被复制,否则它将被移动。 String没有实现Copy,因此它将被移动。
折叠操作可以在追加符之间保存字符串:
let s = format!("some string");
let s = vec!(1,2).iter()
.fold(s, |s, num| s.append("some other string"));
println!("{}",s);
我假设你最终想从向量中读取字符串。如果您只是尝试多次重复操作,则应使用range(0, n)
或std::iter::Repeat::new("some other string").take(n)
作为迭代器来进行折叠。