如何打印 Vec?

Posted

技术标签:

【中文标题】如何打印 Vec?【英文标题】:How to print a Vec? 【发布时间】:2015-07-30 22:53:51 【问题描述】:

我尝试了以下代码:

fn main() 
    let v2 = vec![1; 10];
    println!("", v2);

但是编译器抱怨:

error[E0277]: `std::vec::Vec<integer>` doesn't implement `std::fmt::Display`
 --> src/main.rs:3:20
  |
3 |     println!("", v2);
  |                    ^^ `std::vec::Vec<integer>` cannot be formatted with the default formatter
  |
  = help: the trait `std::fmt::Display` is not implemented for `std::vec::Vec<integer>`
  = note: in format strings you may be able to use `:?` (or :#? for pretty-print) instead
  = note: required by `std::fmt::Display::fmt`

有人为Vec&lt;T&gt; 实现了这个特性吗?

【问题讨论】:

【参考方案1】:
let v2 = vec![1; 10];
println!(":?", v2);

用于字符串和其他可以直接显示给用户的值。没有一种方法可以向用户显示矢量。

:? 格式化程序可以用来调试它,它看起来像:

[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

Display 是提供 背后方法的特征,Debug 是为:? 提供的方法

【讨论】:

这是问题标题的正确答案。也适用于数组,不仅是vec! 有没有办法把矢量格式化得更漂亮,不只是单行打印? @Anatoly 您可以使用替代说明符:#? 使输出分布多行【参考方案2】:

有人为Vec&lt;T&gt; 实现这个特性吗?

没有。

令人惊讶的是,这是一个明显正确的答案;这很少见,因为证明事物不存在通常很难或不可能。那我们怎么能这么确定呢?

Rust 有非常严格的一致性规则,impl Trait for Struct 只能做到:

Trait在同一个箱子里 或与Struct在同一个板条箱中

别无他处;让我们try it:

impl<T> std::fmt::Display for Vec<T> 
    fn fmt(&self, _: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> 
        Ok(())
    

产量:

error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
 --> src/main.rs:1:1
  |
1 | impl<T> std::fmt::Display for Vec<T> 
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
  |
  = note: only traits defined in the current crate can be implemented for a type parameter

此外,要使用 trait,它需要在范围内(因此,您需要链接到它的 crate),这意味着:

您已与Display 的板条箱和Vec 的板条箱链接 既不为Vec实现Display

因此我们得出结论,没有人为Vec 实现Display


作为一种变通方法,如 Manishearth 所述,您可以使用 Debug 特征,该特征可通过 ":?" 作为格式说明符调用。

【讨论】:

报错E0210是否意味着只允许在文件collections/vec.rs中实现trait Display? @highfly22:我的理解是它应该在同一个箱子里,不一定是同一个文件。 什么?所以我不能在模块中临时添加一个 Display trait impl,我需要它作为另一个 crate 中的类型? @BitTickler:不。解决方案是声明一个新类型:struct Mine(That3rdPartyType);,然后是impl Display for Mine 这里是一个“新类型”的例子:play.rust-lang.org/…【参考方案3】:

如果您知道向量包含的元素的类型,您可以创建一个以向量为参数的结构,并为该结构实现Display

use std::fmt::Display, Formatter, Error;

struct NumVec(Vec<u32>);

impl Display for NumVec 
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> 
        let mut comma_separated = String::new();

        for num in &self.0[0..self.0.len() - 1] 
            comma_separated.push_str(&num.to_string());
            comma_separated.push_str(", ");
        

        comma_separated.push_str(&self.0[self.0.len() - 1].to_string());
        write!(f, "", comma_separated)
    


fn main() 
    let numbers = NumVec(vec![1; 10]);
    println!("", numbers);

【讨论】:

不要求你必须知道元素的确切类型;你可以use a generic and allow any type that implements Display 不幸的是 shepmasters gist 不再起作用了。我已经从这里的示例中重建了一个:play.rust-lang.org/…【参考方案4】:

这是一个也适合你的单行:

println!("[]", v2.iter().fold(String::new(), |acc, &amp;num| acc + &amp;num.to_string() + ", "));

Here 是 一个可运行的例子。


在我自己的情况下,我从函数调用中收到了Vec&lt;&amp;str&gt;。我不想将函数签名更改为自定义类型(我可以为此实现 Display 特征)。

对于我的一个案例,我能够将我的 Vec 的显示转换为我直接与 println!() 一起使用的单行,如下所示:

println!("", myStrVec.iter().fold(String::new(), |acc, &arg| acc + arg));

(lambda 可以适应不同的数据类型,或者更简洁的Display trait 实现。)

【讨论】:

【参考方案5】:

是否有任何理由不逐项编写向量的内容而无需以前的收集? *)

use std::fmt::Display, Formatter, Error;

struct NumVec(Vec<u32>);

impl Display for NumVec 
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> 
        let v = &self.0;
        if v.len() == 0 
            return Ok(());
        
        for num in &v[0..v.len() - 1] 
            if let Err(e) = write!(f, ", ", &num.to_string()) 
                return Err(e);
            
        
        write!(f, "", &v[v.len() - 1])
    


fn main() 
    let numbers = NumVec(vec![1; 10]);
    println!("", numbers);

*) 不,没有。

因为我们想要显示一些东西,所以Display trait 是肯定实现的。所以这是正确的Rust,因为:文档说ToString trait:

“对于任何实现了Display trait 的类型,这个特征都会自动实现。因此,ToString 不应该直接实现:Display 应该被实现,你会得到ToString 实现免费。”

特别是在空间有限的微控制器上,我肯定会采用这种解决方案并立即编写。

【讨论】:

以上是关于如何打印 Vec?的主要内容,如果未能解决你的问题,请参考以下文章

如何将打印在控制台上的值存储为矢量?

如何在r中打印可变数量的参数?

在屏幕上打印 BGR 和 HSV 颜色值

如何在Rust中打印变量的类型?

从尾到头打印链表

使用 printf 时 vector<Vec3b> 的格式说明符