跳转到内容

Rust 输出

你已经用过很多次 println! 了。这一页介绍你还会遇到的其他打印宏,以及什么时候该用哪一个。

println! 打印文字,并在末尾加一个换行。print! 做的事一样,但不会换行:

fn main() {
print!("你好,");
print!("世界");
println!("!");
}

输出:

你好,世界!
▶ 动手试一试

注意,三次调用的内容都打印在同一行,只有 println! 会换到新的一行。实际写代码时,你几乎总是用 println!;print! 主要在你需要一点一点拼出一行内容时才派上用场。

你已经见过用 {} 做占位符了。填充它有两种方式:在字符串后面传入值,或者把变量名直接写进花括号里:

fn main() {
let name = "Ferris";
let age = 10;
println!("{} 今年 {} 岁", name, age); // 按位置填充
println!("{name} 今年 {age} 岁"); // 内联写法(结果相同)
}

输出:

Ferris 今年 10 岁
Ferris 今年 10 岁
▶ 动手试一试

两行打印的内容完全一样。内联写法({name})出现得稍晚一些,通常也更好读,所以能用的时候尽量用它。

有时你想把格式化好的文字存成一个 String,而不是立刻打印出来,比如要把它存起来,或者传给另一个函数。这就是 format! 的用途。它的用法和 println! 一模一样,只是不打印,而是返回一个 String:

fn main() {
let name = "Ferris";
let message = format!("你好,{name}!");
println!("{message}");
}

输出:

你好,Ferris!
▶ 动手试一试

普通的 {} 只适用于知道如何把自己显示成文字的值,比如数字、字符串、布尔值。对于元组、结构体这类更复杂的值,用 {} 是无法编译的。这时要改用 {:?}(“调试”格式):

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
42
00003.14
▶ 动手试一试

这些不用死记硬背。只要知道有这些写法,需要对齐数字或四舍五入小数时能想起来就行。

宽度对文字也有效,而且你可以选择值靠哪一边。在 : 后面写 <(左对齐)、>(右对齐)或 ^(居中),再写宽度。还可以在前面加一个填充字符,比如 -:

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 Price
Coffee 3.50
Bagel 2.25
Total 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.50
▶ 动手试一试

2. 生成一个标签,用两种方式打印

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