Rust初步(七):格式化

在Rust中,若是要進行屏幕輸出,或者寫入到文件中,須要對數據進行格式化。這一篇總結一下它所支持的幾種格式化方式。css

這篇文章參考瞭如下官方文檔,不過,按照個人風格,我仍是會突出於C#語言的比較,這樣可能更好懂一些。html

http://rustbyexample.com/hello/print.htmlapp

http://doc.rust-lang.org/std/fmt/ui

http://rustbyexample.com/hello/print/print_debug.htmlthis

http://rustbyexample.com/hello/print/print_display.htmlspa

 

首先,有三個常見的宏,能夠用來作格式化debug

  • format!: write formatted text to String  這個宏能夠將一個文本格式化成String類型(可變字符串,在堆上面分配空間),相似於C#中的String.Format方法。
  • print!: same as format! but the text is printed to the console.  和format!這個宏功能同樣,只不過是輸出到屏幕上。相似於C#中的Console.Write方法。
  • println!: same as print! but a newline is appended. 同上,只不過添加了換行符,相似於C#中的Console.WriteLine方法。

 

既然搞清楚了這三個宏,與C#中有關實現方式的關係,其實就很好理解了。通常這類方法,均可以比較方便地組合字符串,經過佔位符這種東西。在C#中,用{0}表示第一個佔位符,用{1}表示第二個佔位符,依次類推。code

https://msdn.microsoft.com/zh-cn/library/system.string.format(v=vs.110).aspxorm

https://msdn.microsoft.com/zh-cn/library/txafckwd(v=vs.110).aspxhtm

可是Rust提供了一些本身的創新作法,它能夠直接用空的佔位符 {}(這個在C#中不容許的),也能夠用帶序號的佔位符 {0},還直接帶名稱的佔位符{name},一樣,也支持在佔位符裏面指定特殊格式化的符號,例如{:?} 。 這裏有一篇詳細的介紹http://doc.rust-lang.org/std/fmt/ 

fn main() {
    // In general, the `{}` will be automatically replaced with any
    // arguments. These will be stringified.
    println!("{} days", 31);

    // Without a suffix, 31 becomes an i32. You can change what type 31 is,
    // with a suffix.

    // There are various optional patterns this works with. Positional
    // arguments can be used.
    println!("{0}, this is {1}. {1}, this is {0}", "Alice", "Bob");

    // As can named arguments.
    println!("{subject} {verb} {predicate}",
             predicate="over the lazy dog",
             subject="the quick brown fox",
             verb="jumps");

    // Special formatting can be specified after a `:`.
    println!("{} of {:b} people know binary, the other half don't", 1, 2);

    // It will even check to make sure the correct number of arguments are
    // used.
    println!("My name is {0}, {1} {0}", "Bond");
    // FIXME ^ Add the missing argument: "James"

    // Create a structure which contains an `i32`. Name it `Structure`.
    struct Structure(i32);

    // However, custom types such as this structure require more complicated
    // handling. This will not work.
    println!("This struct `{}` won't print...", Structure(3));
    // FIXME ^ Comment out this line.
}

知道了如何作格式化,下面要討論一個問題:具體對象到底怎麼實現本身的字符串表現形式的呢?其實,以前我已經略微介紹到了這個問題

Rust初步(四):在rust中處理時間

 

從上面的例子中,咱們知道,要將一個對象做爲一個字符串輸出的話,就須要對其進行轉換。咱們在C#中就是要實現ToString方法,在Rust裏面,分別有兩個方法Debug和Display方法。若是是元類型(Primitive Type),固然是沒有問題的,基本上都已經實現了。

  • fmt::Debug: Uses the {:?} marker. Format text for debugging purposes.  若是咱們的佔位符使用{:?},默認會調用對象的Debug方法,若是沒有,則會報告錯誤
  • fmt::Display: Uses the {} marker. Format text in a more elegant, user friendly fashion.若是咱們的佔位符使用{},,默認會調用對象的Display方法,若是沒有,則會報告錯誤

注意,除了這兩種形式,還有其餘一些格式化輸出方式

  • unspecified -> Display
  • ? -> Debug
  • o –> Octal //8進制
  • x –> LowerHex //16進制
  • X -> UpperHex
  • p –> Pointer
  • b –> Binary //二進制
  • e -> LowerExp
  • E -> UpperExp

下面考慮一個例子,來加深理解

struct Point{ //自定義一個結構體
    x:i32,
    y:i32
}

fn main() {
    let p = Point{x:3,y:5};
    println!("{}",p.x);//打印x,這會成功
    println!("{:?}",p);//直接打印整個結構體,由於沒有實現Debug,會失敗
    println!("{}",p);//直接打印整個結構體,由於沒有實現Display,會失敗
}

這個例子連編譯都不會經過

image

那麼,如何實現Debug和Display呢?

Debug相對來講很簡單,只要聲明一下便可

#[derive(Debug)]
struct Point{ //自定義一個結構體
    x:i32,
    y:i32
}

fn main() {
    let p = Point{x:3,y:5};
    println!("{}",p.x);//打印x,這會成功
    println!("{:?}",p);//直接打印整個結構體,由於已經實現Debug,會成功
    
}

那麼,它是怎樣輸出的呢?

image

實際上就很相似於C#中全部Object的默認實現(ToString)

 

相比而言,Display是須要手工來實現的,大體以下

use std::fmt;

#[derive(Debug)]
struct Point{ //自定義一個結構體
    x:i32,
    y:i32
}

impl fmt::Display for Point{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
          write!(f, "x爲{},y爲{}", self.x,self.y)
      }

}

fn main() {
    let p = Point{x:3,y:5};
    println!("{}",p);//直接打印整個結構體,由於已經實現Debug,會成功

}

輸出結果以下

image

相關文章
相關標籤/搜索