为什么截断的字符串Rust打印为一对空括号?

时间:2017-08-23 10:24:39

标签: rust

我有

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`

我做错了什么?如果我使用{:?},那么我会获得()而不是格式化的字符串。

3 个答案:

答案 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];