我有
use std::io;
fn main() {
println!("CHAR COUNT");
let mut guess = String::new();
io::stdin().read_line(&mut guess).expect(
"Failed to read line",
);
let string_length = guess.len() - 2;
let correct_string_length = guess.truncate(string_length);
println!("Your text: {}", guess);
println!("Your texts wrong length is: {}", string_length);
println!("Your texts correct length: {}", correct_string_length);
}
最后一行给了我
error[E0277]: the trait bound `(): std::fmt::Display` is not satisfied
--> src/main.rs:15:47
|
15 | println!("Your texts correct length: {}", correct_string_length);
| ^^^^^^^^^^^^^^^^^^^^^ `()` cannot be formatted with the default formatter; try using `:?` instead if you are using a format string
|
= help: the trait `std::fmt::Display` is not implemented for `()`
= note: required by `std::fmt::Display::fmt`
我做错了什么?如果我使用{:?}
,那么我会获得()
而不是格式化的字符串。
答案 0 :(得分:9)
如有疑问,请转到docs - 这是String::truncate
的功能签名:
fn truncate(&mut self, new_len: usize)
注意两件事:
self
为&mut
。由此,问题变得非常清楚 - truncate
不返回新的截断字符串,它会截断现有的字符串。
起初看起来有些不太直观,但Rust API往往不会在内存中分配新对象,除非你特别要求它们 - 如果你再也不会使用guess
,那么它就是无效的创造一个全新的String
。如果您想制作截断的副本,那么您需要明确:
let truncated = guess.clone();
truncated.truncate(string_length);
或者如果你只是想引用现有字符串的 part ,你可以做Ryan的答案所暗示的。
答案 1 :(得分:5)
只是为了赞美其他答案..
尝试在Rust中截断不在字符边界上的字符串将导致运行时出现紧急情况。
所以虽然现在有效:
let correct_string_length = &guess[..string_length];
如果您尝试截断字符较宽的字符串,则代码会在运行时出现混乱。如果您要截断用户输入,则尤其如此。谁知道它可能是什么。例如:
fn main() {
let s = "Hello, 世界";
println!("{}", &s[..8]); // <--- panic
}
您可以使用str::is_char_boundary(usize)
方法确保您不会意外地分解广角:
fn print_safely(s: &str, mut idx: usize) {
loop {
if s.is_char_boundary(idx) || idx >= s.len() - 1 {
break;
}
idx += 1;
}
println!("{}", &s[..idx]);
}
用户输入可以是任何东西,所以这只是需要考虑的事情。
游乐场链接:http://play.integer32.com/?gist=632ff6c81c56f9ba52e0837ff25939bc&version=stable
答案 2 :(得分:4)
truncate
operates in place,这就是它返回()
的原因。看起来你只是在寻找一个常规的非变异子字符串:
let correct_string_length = &guess[..string_length];