在rust中, 模块std::fmt 用来格式化输出字符串,可以使用format!对字符串进行格式化。print!、println!与format!非常接近,唯一不同的地方在于 print!会将要输出的内容打印到控制台,println! 会在输出的内容打印到控制台后进行换行。
以下是一些格式化输出的例子
print!("hello"); // => "hello"
print!("hello,{}!","world"); // => "hello world!"
print!("the num is {}", 1); // => "the num is 1"
print!("{:?}", (3,4)); // => "(3,4)"
print!("{val}", val=4); // => "4"
print!("{} {}", 1,2); // => "1 2"
print!("{:04}",42); // => "0042"
print! 接受的是可变参数,第一个参数是一个字符串常量,它表示最终输出的字符串的格式,第一个参数可以看到类似{}的符号 ,它相当于占位符,可以在最终的结果里面按照指定的规则进行替换。如下所示:
print!("{}{}",1,2); //=> "12"
print!("{1}{0}",1,2); //=>"21"
print!("{1}{}{0}{}",1,2); //=>2112
##带变量的名称
除了指定参数的位置外, print!也指定了参数的名字,如下:
print!("{arg}",arg = "tyest"); //=>"test"
print!("{name} {}",1, name =2); //=>"2 1"
print!("{a} {c} {b}",a ="a",b ='b', c=3); //=>"a 3 b"
需要注意的是,带名字的参数必须放在不带名字的参数的后面,以下例子无法通过编译:
print!("{abc} {1}", abc = "def", 2);
例子如下:
以下是一些格式化输出的例子
println!("Hello {:5}!", "x");
println!("Hello {:1$}!", "x", 5);
println!("Hello {1:0$}!", 5, "x");
println!("Hello {:width$}!", "x", width = 5);
//以上的所有结果都为 "hello x !"
可以看到,例子中{}里面多了一个:,后面的参数叫做“最小宽度“,如果宽度不够,需要填充和对齐。“最小宽度”可以指定,指定的时候 会在最后跟一个 美元符号。冒号前面可以指定被格式化的参数的位置,如果上面第三个例子不指定,结果就会改变,如下:
print!("hello {:1$}!{}","x",5); //=>hello x !5
如果不指定对齐方式,rust 会用默认的方式进行填充和对齐,对于非数字,采用的是空格填充左对齐,数字采用的是空格填充右对齐。查看以下例子看如何对齐:
assert_eq!(format!("Hello {:<5}!", "x"), "Hello x !");
assert_eq!(format!("Hello {:-<5}!", "x"), "Hello x----!");
assert_eq!(format!("Hello {:^5}!", "x"), "Hello x !");
assert_eq!(format!("Hello {:>5}!", "x"), "Hello x!");
1.fill<: 表示左对齐,用fill进行填充,比如上面例子的第1个和第2个。
2.fill^: 居中对齐。
3.fill>: 右对齐。
assert_eq!(format!("Hello {:+}!", 5), "Hello +5!");
assert_eq!(format!("{:#x}!", 27), "0x1b!");
assert_eq!(format!("Hello {:05}!", 5), "Hello 00005!");
assert_eq!(format!("Hello {:05}!", -5), "Hello -0005!");
assert_eq!(format!("{:#010x}!", 27), "0x0000001b!");
1.+: 表示永远打印数字的符号,默认情况下不会打印正数的符号。
2.#: 表示采用其他形式来输出结果:
#b: 表示用二进制输出,比如下面的例子,我们可以看到最小宽度是10,并且10包含了0b这两个字符。
println!("Hello {:#010b}!", 10); //=> Hello 0b00001010!
#o: 表示用8进制输出
#x : 表示用16进制小写输出(即:a,b,c,d,e,f)
#X : 表示用16进制大写输出(即:A,B,C,D,E,F)
0:表示整数使用0进行填充。对于正数1,{:08}的结果是00000001,8表示是宽度;对于-1,{:08}的结果是-0000001,注意-占了一位。
精度的语法和前面宽度的语法有点类似,先介绍一些语法,然后再举例说明实际的用法。
.N:其中N表示精度值。
.N$:和宽度一样,可以指定某个参数来表示精度值。
.* : 它的意思是{}会接收两个输入,第一个输入表示的是精度,第二个输入将要被格式化的值。如果采用以下的形式:{:.*},那么是要被格式化的值,之前的一个参数表示精度。
对于非数字类型的数据,精度相当于最大长度,如果格式化结果的长度比精度大,会进行截断,下面是一个例子:
//结果都是: Hello abcdefg!
println!("Hello {:.1$}!", "abcdefg", 10);
println!("Hello {:.10}!", "abcdefg");
println!("Hello {0:.10}!", "abcdefg");
println!("Hello {:.*}!", 10, "abcdefg");
println!("Hello {1:.*}!", 10, "abcdefg");
//下面这个结合宽度和精度
println!("Hello {0:+>7.4}!", "abcdefg"); //=> Hello +++abcd!
对于整数,精度会被忽略,对于浮点数,精度表示小数点之后需要打印多少位。
// Hello {arg 0 ("x")} is {arg 2 (0.01) with precision specified in arg 1 (5)}
println!("Hello {0} is {2:.1$}", "x", 5, 0.01);