Rust 输出
你已经用过很多次 println! 了。这一页介绍你还会遇到的其他打印宏,以及什么时候该用哪一个。
println! 和 print!
Section titled “println! 和 print!”println! 打印文字,并在末尾加一个换行。print! 做的事一样,但不会换行:
fn main() { print!("你好,"); print!("世界"); println!("!");}输出:
你好,世界!注意,三次调用的内容都打印在同一行,只有 println! 会换到新的一行。实际写代码时,你几乎总是用 println!;print! 主要在你需要一点一点拼出一行内容时才派上用场。
占位符:{} 和变量名
Section titled “占位符:{} 和变量名”你已经见过用 {} 做占位符了。填充它有两种方式:在字符串后面传入值,或者把变量名直接写进花括号里:
fn main() { let name = "Ferris"; let age = 10;
println!("{} 今年 {} 岁", name, age); // 按位置填充 println!("{name} 今年 {age} 岁"); // 内联写法(结果相同)}输出:
Ferris 今年 10 岁Ferris 今年 10 岁两行打印的内容完全一样。内联写法({name})出现得稍晚一些,通常也更好读,所以能用的时候尽量用它。
format!:生成字符串而不是打印
Section titled “format!:生成字符串而不是打印”有时你想把格式化好的文字存成一个 String,而不是立刻打印出来,比如要把它存起来,或者传给另一个函数。这就是 format! 的用途。它的用法和 println! 一模一样,只是不打印,而是返回一个 String:
fn main() { let name = "Ferris"; let message = format!("你好,{name}!"); println!("{message}");}输出:
你好,Ferris!用 {:?} 进行调试打印
Section titled “用 {:?} 进行调试打印”普通的 {} 只适用于知道如何把自己显示成文字的值,比如数字、字符串、布尔值。对于元组、结构体这类更复杂的值,用 {} 是无法编译的。这时要改用 {:?}(“调试”格式):
fn main() { let point = (3, 7); println!("{:?}", point);}输出:
(3, 7)如果值比较大,想要排版更好看的多行格式,就用 {:#?}(美化打印):
fn main() { let point = (3, 7); println!("{:#?}", point);}输出:
( 3, 7,)几个经常用到的格式化技巧:
fn main() { let pi = 3.14159; println!("{:.2}", pi); // 保留 2 位小数 -> 3.14 println!("{:5}", 42); // 补齐到宽度 5 -> " 42" println!("{:08.2}", pi); // 用 0 补齐 -> 00003.14}输出:
3.14 4200003.14这些不用死记硬背。只要知道有这些写法,需要对齐数字或四舍五入小数时能想起来就行。
对齐文字,以及打印花括号
Section titled “对齐文字,以及打印花括号”宽度对文字也有效,而且你可以选择值靠哪一边。在 : 后面写 <(左对齐)、>(右对齐)或 ^(居中),再写宽度。还可以在前面加一个填充字符,比如 -:
fn main() { let coffee = 3.5; let bagel = 2.25;
println!("{:-^20}", " MENU "); println!("{:<12}{:>8}", "Item", "Price"); println!("{:<12}{:>8.2}", "Coffee", coffee); println!("{:<12}{:>8.2}", "Bagel", bagel); println!("{:<12}{:>8.2}", "Total", coffee + bagel);}输出:
------- MENU -------Item PriceCoffee 3.50Bagel 2.25Total 5.75这个例子里的文字保留了英文:宽度按字符个数计算,而一个汉字在屏幕上占两个字母的宽度,换成中文后列就对不齐了。
逐段拆解 {:>8.2}:> 表示右对齐,8 是宽度,.2 表示保留两位小数。数字右对齐后,小数点就能上下对齐,这也是收据和表格都这样排版的原因。
如果想在输出里打印一个真正的 { 怎么办?因为花括号表示“占位符”,所以要把它们写两遍:{{ 打印出 {,}} 打印出 }。
fn main() { println!("集合:{{{}, {}}}", 1, 2);}输出:
集合:{1, 2}把商品名 "笔记本" 和价格 2.5 存进变量,然后打印 笔记本售价 ¥2.50。提示:{:.2} 会四舍五入到两位小数,而且内联写法也能用:{price:.2}。
查看答案
fn main() { let item = "笔记本"; let price = 2.5; println!("{item}售价 ¥{price:.2}");}输出:
笔记本售价 ¥2.502. 生成一个标签,用两种方式打印
Section titled “2. 生成一个标签,用两种方式打印”用 format! 把名字 "ferris" 和数字 7 拼成标签 ferris-7。分别用 {} 和 {:?} 各打印一次,找找两者的区别。提示:format! 接受的占位符和 println! 完全相同。
查看答案
fn main() { let name = "ferris"; let id = 7; let label = format!("{name}-{id}");
println!("{label}"); println!("{label:?}");}输出:
ferris-7"ferris-7"调试打印会把文字连同引号一起显示,这样你就能看清它从哪里开始、到哪里结束。当值里混进了多余的空格时,这一点特别有用。
println!打印后会换行;print!不会。{}和{name}是占位符,用于能用Display显示自己的值。format!的用法和println!一样,但返回一个String,而不是打印出来。{:?}(以及{:#?})用于调试打印,包括那些{}处理不了的值。{:.2}控制小数位数;<、>、^加上宽度可以对齐文字;{{和}}打印花括号本身。
小测验
1. println! 和 print! 有什么区别?
2. 打印元组时,为什么要用 {:?} 而不是 {}?
得分: 0 / 2
std::fmt— 标准库文档(英文):完整的格式化选项列表,包括宽度、填充、对齐和精度。- 格式化输出 —《通过例子学 Rust》:位置参数、命名参数、补齐和对齐的可运行示例。
- 调试(Debug)—《通过例子学 Rust》:
{:?}和{:#?}是怎么工作的,以及你自己的类型如何获得它们。 println!— 标准库文档(英文):println!的官方参考,并附有print!和eprintln!的链接。format!— 标准库文档(英文):用同样的格式化规则生成一个String。