Rust初步(七):格式化


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

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

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

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

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

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

 

首先,有三個常見的宏,可以用來做格式化

  • 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}表示第二個占位符,依次類推。

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

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

但是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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM