一、什么是格式化输出?
Rust 的格式化输出功能强大且灵活,通过println!
、print!
、 format!
等宏实现。
支持多种占位符(如 {} 、 {:?} 、 {:#?}
)和格式化选项(如宽度、精度、对齐方式),能够满足从简单文本输出到复杂数据结构调试的需求。
Rust 还允许通过实现 Display
和 Debug
特征来自定义类型格式化行为,同时支持动态精度、宽度控制和元组结构体等高级用法。
二、基础格式化
1. println!
宏基础
在 src/main.rs
中添加:
rust
// 基础字符串输出
println!("Hello, World!");
// 变量插入
let name = "Alice";
println!("Name: {}", name);
// 多变量插入
let age = 30;
println!("{} is {} years old", name, age);
关键特性:
{}
是占位符,按顺序匹配参数- 自动类型推导,无需指定类型
- 支持任意实现了
Display
trait 的类型
2. 基础类型格式化
rust
// 数字格式化
let num = 42;
println!("Decimal: {}", num);
println!("Hex: {:x}", num); // 小写十六进制
println!("Binary: {:b}", num); // 二进制
println!("Debug: {:?}", num); // 调试格式
// 浮点数控制
let pi = 3.1415926;
println!("2 decimals: {:.2}", pi);
println!("Scientific: {:e}", pi);
常用格式说明符:
x
/X
:十六进制(小写/大写)b
:二进制o
:八进制e
:科学计数法.N
:保留 N 位小数
三、高级格式化技巧
1. 对齐与填充
rust
// 右对齐填充
println!("{:>10}", "test"); // 输出 " test"
// 左对齐填充
println!("{:<10}", "test"); // 输出 "test "
// 零填充
println!("{:0>5}", 42); // 输出 "00042"
// 符号填充
println!("{:+>6}", 10); // 输出 " +10"
println!("{:-<6}", 10); // 输出 "10----"
2. 宽度与精度控制
rust
// 固定宽度
println!("{:5}", 42); // 输出 " 42"
// 浮点数精度组合
println!("{:10.3}", pi); // 输出 " 3.142"
// 截断字符串
println!("{:.3}", "Hello"); // 输出 "Hel"
3. 类型强制转换
rust
// 显式指定类型
println!("0x{:x}", 255); // 输出 "0xff"
println!("0o{:o}", 255); // 输出 "0o377"
// 调试输出
println!("{:?}", (1, "a")); // 输出 "(1, \"a\")"
四、自定义格式化
1. 实现 Display
trait
rust
use std::fmt;
struct Point {
x: i32,
y: i32,
}
impl fmt::Display for Point {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "({}, {})", self.x, self.y)
}
}
fn main() {
let p = Point { x: 10, y: 20 };
println!("Point: {}", p); // 输出 "Point: (10, 20)"
}
2. 调试输出 (Debug
trait)
rust
#[derive(Debug)]
struct Person {
name: String,
age: u8,
}
fn main() {
let person = Person {
name: "Bob".to_string(),
age: 45,
};
println!("{:?}", person); // 输出 "Person { name: "Bob", age: 45 }"
}
3. 自定义格式参数
rust
struct Temperature(f32);
impl fmt::Display for Temperature {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let precision = f.precision().unwrap_or(2);
write!(f, "{:.*}°C", precision, self.0)
}
}
fn main() {
let temp = Temperature(25.678);
println!("{}", temp); // 输出 "25.68°C"
println!("{:.1}", temp); // 输出 "25.7°C"
}
五、错误处理与调试
1. 编译时类型检查
rust
// 类型不匹配会触发编译错误
// println!("{} {}", 42, "text"); // 错误:类型不匹配
// 显式指定类型
println!("{} {}", 42 as i32, "text"); // 正确
2. 格式化错误处理
rust
use std::fmt;
struct MyError;
impl fmt::Debug for MyError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Custom error message")
}
}
fn main() {
let err = MyError;
eprintln!("Error: {:?}", err); // 输出 "Error: Custom error message"
}
六、性能优化技巧
1. 避免重复格式化
rust
// 低效方式
for i in 0..1000 {
println!("Processing item {}", i);
}
// 高效方式(预格式化)
let format_str = "Processing item {}";
for i in 0..1000 {
println!(format_str, i);
}
2. 使用 write!
宏
rust
use std::io::Write;
fn main() {
let mut buffer = String::new();
write!(&mut buffer, "Number: {}, {}", 10, 20).unwrap();
println!("{}", buffer); // 输出 "Number: 10, 20"
}
七、实战案例:表格输出
rust
use prettytable::{Table, Row, Cell};
fn main() {
let mut table = Table::new();
table.add_row(Row::new(["Name", "Age"]));
table.add_row(Row::new(["Alice", Cell::new("30").align(prettytable::Alignment::RIGHT)]));
table.add_row(Row::new(["Bob", "25"]));
table.printstd();
}
在 Cargo.toml
中添加依赖:
toml
[dependencies]
prettytable = "0.8"