2015-05-19 19 views
27

Tôi đã thử các mã sau:Làm thế nào để in một Vec?

let v2 = vec![1; 10]; 
println!("{}", v2); 

Nhưng trình biên dịch phàn nàn rằng:

error[E0277]: the trait bound `std::vec::Vec<{integer}>: std::fmt::Display` is not satisfied 
--> src/main.rs:3:20 
    | 
3 |  println!("{}", v2); 
    |     ^^ trait `std::vec::Vec<{integer}>: std::fmt::Display` not satisfied 
    | 
    = note: `std::vec::Vec<{integer}>` cannot be formatted with the default formatter; try using `:?` instead if you are using a format string 
    = note: required by `std::fmt::Display::fmt` 

Có ai thực hiện đặc điểm này cho Vec<T>?

Trả lời

28

Có ai thực hiện đặc điểm này cho Vec<> không?

số

Và đáng ngạc nhiên, đây là một câu trả lời được trình diễn chính xác; điều này hiếm khi chứng minh sự vắng mặt của những thứ thường khó hoặc không thể. Vậy làm thế nào chúng ta có thể chắc chắn như vậy?

Rust có những quy định chặt chẽ rất nghiêm ngặt, các impl Trait for Struct chỉ có thể được thực hiện:

  • hoặc trong các thùng giống như Trait
  • hoặc trong thùng giống như Struct

và nơi nào khác ; chúng ta hãy try it:

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

sản lượng:

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

Bên cạnh đó, sử dụng một trait, nó cần phải được trong phạm vi (và do đó, bạn cần phải được liên kết với thùng của nó), có nghĩa là:

  • bạn được liên kết cả với thùng của Display và thùng của Vec
  • không thực hiện Display cho Vec

và do đó dẫn chúng ta đến kết luận rằng không có ai thực hiện Display cho Vec.


Là một công trình xung quanh, như được chỉ ra bởi Manishearth, bạn có thể sử dụng Debug đặc điểm, đó là invokable qua "{:?}" như một specifier định dạng.

+0

Lỗi E0210 có nghĩa là nó chỉ được phép thực hiện đặc tính Hiển thị trong tập hợp tệp/vec.rs không? – highfly22

+1

@ highfly22: sự hiểu biết của tôi là nó phải ở trong cùng một thùng, không nhất thiết phải cùng một tệp. –

+1

Cái gì? Vì vậy, tôi không thể ad-hoc thêm một tính năng hiển thị impl trong mô-đun mà tôi cần nó cho một loại trong một thùng? – BitTickler

37
let v2 = vec![1; 10]; 
println!("{:?}", v2); 

{} là dành cho chuỗi và các giá trị khác có thể được hiển thị trực tiếp cho người dùng. Không có cách nào duy nhất để hiển thị một vector cho một người dùng, tuy nhiên {:?} thể được sử dụng để gỡ lỗi nó, và nó sẽ trông giống như:

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

Display là đặc điểm cung cấp các phương pháp sau {}, và Debug là dành cho {:?}

13

Nếu bạn biết loại phần tử chứa vector, bạn có thể tạo cấu trúc lấy vector làm đối số và triển khai Display cho cấu trúc đó.

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); 
} 
+0

Không yêu cầu bạn phải biết loại * chính xác * của các phần tử; bạn có thể [sử dụng một generic và cho phép bất kỳ loại nào thực hiện 'Display'] (http://play.integer32.com/?gist=38a0d87690419c4c1e7280c95e155d0b&version=stable). – Shepmaster

1

Đây là một lớp lót cũng nên làm việc cho bạn:

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

Here là một ví dụ Runnable.


Trong trường hợp của riêng tôi, tôi đã nhận được Vec<&str> từ một cuộc gọi chức năng. Tôi không muốn thay đổi chữ ký chức năng thành kiểu tùy chỉnh (mà tôi có thể thực hiện đặc điểm Display).

Đối với tôi một trường hợp, tôi đã có thể xoay màn hình của Vec của tôi vào một lớp lót mà tôi sử dụng với println!() trực tiếp như sau:

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

(Lambda có thể được điều chỉnh để sử dụng với các kiểu dữ liệu khác nhau, hoặc để thực hiện ngắn gọn hơn Display đặc điểm.)

Các vấn đề liên quan