iT邦幫忙

2023 iThome 鐵人賽

DAY 27
0

第一天的時候有介紹到, Rust 要印出東西的方法是 print 以及 println!

不過我們在這幾天印出東西的時候又有加上 {} 以及 {:?}

究竟他們有什麼差別呢?

print! println! format!

print! 與 println! 的差別在於有沒有換行

那 format! 又是什麼呢

我們來用這三個印出東西看看

fn main() {
    let a = 1;
    println!("this is println! {}", a);
    print!("this is print! {}", a);
    format!("this is format! {}", a);
}

執行的時候發現 format! 不見了,為什麼呢?

> cargo run

this is println! 1
this is print! 1

format!

format! 的用途不在於印出來,而是要將資料轉變成 String

我們來看以下例子

fn main() {
    let a = 1;
    println!("this is println! {}", a);
    let b = format!("this is format! {}", a);
    println!("{}", b)
}
> cargo run

this is println! 1
this is format! 1

現在我們知道 print! println! format! 之間的差別了

再來還要介紹印出錯誤訊息的方法

eprint! 與 eprintln!

我們在開發的時候,會使用 print! println! 來看結果

不過在印出錯誤訊息的時候,可以用 eprint! eprintln!

不過參數中的訊息你還是得自己打,他不會因此幫你找出錯誤訊息來

fn main() {
    eprintln!("我是錯誤訊息");
}
> cargo run

我是錯誤訊息

Rust 的輸出方法很多種,他們各有用途,不過在以上的方法中,都會使用 {} 以及 {:?} 來印出變數

{}

{} 會有 std::fmt::Display 的 trait ,讓我們可以透過 {} 印出東西來

通常在印出基本類型,如 i32 f64 &str 的時候會使用到

如果我們要印出結構中的值,這時候就會需要 std::fmt::Display 這個 trait 了

struct A {
    aa: i32,
    bb: i32,
}

fn main() {
    let instance = A { aa: 1, bb: 2 };
    println!("aa: {}, bb: {}", instance.aa, instance.bb);
}
> cargo run

aa: 1, bb: 2

不過為什麼有時候需要用 {:?}

{:?}

以剛剛的例子來看,假如今天要印出一整個結構,就沒辦法用 {} 印出

#[derive(Debug)]
struct A {
    aa: i32,
    bb: i32,
}

fn main() {
    let instance = A { aa: 1, bb: 2 };
    println!("A = {}", instance);
}

我們來看錯誤訊息,他要告訴我們的是, A 沒辦法實現std::fmt::Display 特徵

不過其實他不是真的沒辦法實現,而是我們需要手動去實現,

不過手動方式並沒不是加上一兩行程式碼就行,

必須要寫一大串的程式碼,有點麻煩

最快的方式就是實現 std::fmt::Debug 這個 trait

> cargo run

error[E0277]: `A` doesn't implement `std::fmt::Display`
 --> src/main.rs:9:24
  |
9 |     println!("A = {}", instance);
  |                        ^^^^^^^^ `A` cannot be formatted with the default formatter
  |
  = help: the trait `std::fmt::Display` is not implemented for `A`
  = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
  = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)

For more information about this error, try `rustc --explain E0277`.
error: could not compile `hello_world` (bin "hello_world") due to previous error

那我們就來改掉

#[derive(Debug)]
struct A {
    aa: i32,
    bb: i32,
}

fn main() {
    let instance = A { aa: 1, bb: 2 };
    println!("A = {:?}", instance);
}
> cargo run

A = A { aa: 1, bb: 2 }

而且結構還必須要掛上 #[derive(Debug)] ,如果沒特別掛上去的話,他就會出錯唷

另外,我們還可以顯示更完整的樣子,讓他看起來更像「結構」一點

{:#?}

其實他跟 {:?} 沒有什麼差異,只差在於輸出的樣子夠不夠像型態的樣子

以下面例子來看

#[derive(Debug)]
struct A {
    aa: i32,
    bb: i32,
}

fn main() {
    let instance = A { aa: 1, bb: 2 };
    println!("A = {:#?}", instance);
}
> cargo run

A = A {
    aa: 1,
    bb: 2,
}

以上是輸出的基本介紹,我們明天會再介紹更多的用法


上一篇
Day 26 - 泛型 part 2
下一篇
Day 28 - 輸出 part 2
系列文
成為程式界的 F1 賽車手,用 30 天認識 Rust 30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言