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

相关文章
相关标签/搜索