目录- 字符串
- String-动态字符串
- &str-字符串切片
- &str与String间转换
- 常用操作
- 格式化
- 参数指定
- 填充与对齐
- 精度
- 类型格式
- 整数类型
- 浮点数类型
- 通用与特殊类型
- 标志(Flags)
- 特殊格式
- 自定义Display获取参数
Rust 提供了多种字符串类型和强大的格式化工具。
字符串
Rust 中主要有两种字符串类型:&str(字符串切片)和String(动态字符串),二者均基于UTF-8 编码。
String-动态字符串
String是标准库提供的拥有所有权的动态字符串类型,存储在堆上:
- 可变:可通过方法修改内容(如添加、删除字符)。
- 动态分配:内存会根据内容自动扩容。
- 所有权:
String拥有其数据,赋值或传递时会触发所有权转移。
创建:
let mut s = String::new(); // 空字符串
let s = "initial".to_string(); // 从字面量转换
let s = String::from("initial"); // 同上
let s = format!("Hello {}", "world"); // 通过格式化宏创建
&str-字符串切片
&str是对一段 UTF-8 编码字符串的不可变引用,它不拥有数据所有权,仅作为 “视图” 存在:
- 不可变:无法直接修改
&str指向的内容。 - 轻量:由两部分组成(指针 + 长度),不分配堆内存,传递时无需复制数据。
- 字面量默认类型:代码中的字符串字面量(如
"hello")本质上是&'static str,生命周期为整个程序运行期。
let s: &str = "hello world"; // 字符串字面量,类型为&'static str
let slice: &str = &s[0..5]; // 从s中截取切片,结果为"hello"
&str与String间转换
String → &str:通过as_str()方法或直接引用(&s),因为String实现了Deref<Target=str>,会自动解引用为&str。
let s = String::from("test");
let s_slice: &str = s.as_str(); // 显式转换
let s_slice2: &str = &s; // 自动解引用,更常用
&str → String:通过String::from或to_string()。
let slice = "hello";
let s = String::from(slice); // 转换为String
let s2 = slice.to_string(); // 等价方式
常用操作
| 分类 | 方法 / 操作 | 适用类型 | 说明 |
|---|
| 创建 | String::new() | String | 创建空字符串 | | String::from("abc") | String | 从字面量创建 | | "abc".to_string() | String | 从 &str 创建 String | | String::with_capacity(n) | String | 预分配容量,减少重分配 | | 转换 | s.as_str() | String | 转换为 &str | | s.into_bytes() | String | 转换为 Vec<u8> | | String::from_utf8(v) | Vec<u8> | 从字节向量还原字符串 | | s.to_string() | &str | 创建新 String | | 长度 | s.len() | String /&str | 返回字节长度(不是字符数) | | s.chars().count() | String /&str | 返回字符数(Unicode scalar) | | 判断 | s.is_empty() | String /&str | 是否为空字符串 | | s.contains("ab") | String /&str | 是否包含子串 | | s.starts_with("ab") | String /&str | 是否以指定子串开头 | | s.ends_with("ab") | String /&str | 是否以指定子串结尾 | | 拼接 | s.push('a') | String | 追加单个字符 | | s.push_str("abc") | String | 追加字符串切片 | | s1 + &s2 | String + &str | 拼接(移动左侧) | | format!("{}{}", a, b) | 任意 | 格式化拼接,不移动 | | 截取/分割 | &s[a..b] | &str | 按字节切片(需在字符边界) | | s.split(',') | String /&str | 按分隔符分割为迭代器 | | s.split_whitespace() | String /&str | 按空白分割 | | s.lines() | String /&str | 按行分割 | | 修剪 | s.trim() | String /&str | 去除首尾空白 | | s.trim_start() /
trim_end() | String /&str | 去除首或尾空白 | | 替换 | s.replace("a","b") | String /&str | 全部替换 | | s.replacen("a","b",n) | String /&str | 替换前 n 次 | | 大小写 | s.to_lowercase() | String /&str | 转小写 | | s.to_uppercase() | String /&str | 转大写 | | 查找 | s.find("ab") | String /&str | 返回首个匹配位置(Option) | | s.rfind("ab") | String /&str | 从后往前找 | | 迭代 | s.chars() | String /&str | 按字符迭代 | | s.bytes() | String /&str | 按字节迭代 | | 比较 | s1 == s2 | String /&str | 内容比较(UTF-8 安全) | | 拷贝 / 克隆 | s.clone() | String | 深拷贝(堆上内容复制) | | 清空 / 容量 | s.clear() | String | 清空内容 | | s.capacity() | String | 当前容量 | | s.reserve(n) | String | 预留额外容量 | | 字节访问 | s.as_bytes() | String /&str | 获取字节切片 | | 连接 Vec | vec.join(",") | Vec<&str> | 用分隔符连接 | | 格式化输出 | format!() | 任意 | 返回格式化字符串 |
格式化
Rust 提供了一套强大的格式化宏,用于字符串拼接、输出等场景,核心是format!(返回String),以及衍生的print!(打印到标准输出)、println!(带换行的打印)、eprint!(打印到标准错误)等。
格式化语法说明:
{[argument][:[fill][align][width][.precision][type]]}
// 动态宽度+精度(后面需要$)
println!("{value:>width$.prec$}",
value=3.14159,
width=10,
prec=3); // " 3.142"
// 带前缀的十六进制
println!("{:#08x}", 42); // "0x00002a"
// 命名参数+格式化
println!("{name:*^10}", name="ALICE"); // "**ALICE***"
参数指定
{argument}用于指定要格式化的参数,默认省略(按顺序)
| 形式 | 说明 | 示例 | 输出结果 |
|---|
| 省略 | 按参数顺序匹配(默认) | println!("{}, {}", "a", "b") | a, b | 位置索引{n} | 按索引n(从 0 开始)匹配 | println!("{1}, {0}", "a", "b") | b, a | 命名{name} | 按参数名匹配 | println!("{x}, {y}", x=1, y=2) | 1, 2 |
填充与对齐
语法片段:[fill][align][width]
fill:任意单字符(默认空格);使用fill时需要同时指定align+width。align:<(左对齐)、>(右对齐,默认)、^(居中)。width:最小字段宽度(整数),不足时使用 fill 填充。
| 形式 | 说明 | 示例 | 输出结果 |
|---|
固定宽度{:w} | 指定最小宽度 | println!("width: [{:*^5}]", 123); | [*123*] | 动态宽度{:width$} | 宽度由参数指定($是必须的) | println!("[{:w$}]", 123, w=5); | [ 123] |
format!("{:>8}", "hi") // 右对齐 -> " hi"
format!("{:<8}", "hi") // 左对齐 -> "hi "
format!("{:^8}", "hi") // 居中 -> " hi "
format!("{:0>5}", 42) // 填充字符 '0', 右对齐 -> "00042"
精度
语法片段:.precision(写作 .N 或 动态 .*)
| 适用类型 | 含义 | 示例 | 输出结果 |
|---|
| 字符串 | 最大长度(超过则截断) | println!("{:.3}", "hello") | hel | | 浮点数 | 小数位数(四舍五入) | println!("{:.2}", 3.1415) | 3.14 | | 整数 | 最小位数(不足补 0,超过则原样输出) | println!("{:.4}", 12) | 0012 | 动态精度{:.*} | 精度由参数指定(前一个参数为精度值) | println!("{}-{:.*}","ab", 2, 3.1415) | ab-3.14 |
类型格式
指定数据的格式化类型,将数据转换为特定格式的字符串。
整数类型
整数类型(i8/i16/i32/i64/u8/u16/…/usize/isize):
| 说明符 | 作用 | 示例 | 输出结果 |
|---|
b | 二进制 | println!("{:b}", 10) | 1010 | o | 八进制 | println!("{:o}", 10) | 12 | d | 十进制(默认) | println!("{:d}", 10) | 10 | x | 小写十六进制 | println!("{:x}", 255) | ff | X | 大写十六进制 | println!("{:X}", 255) | FF |
浮点数类型
浮点数类型(f32/f64):
| 说明符 | 作用 | 示例 | 输出结果 |
|---|
f | 小数形式(默认) | println!("{:f}", 123.456) | 123.456000 (默认 6 位小数) | e | 科学计数法(小写 e) | println!("{:e}", 123.456) | 1.234560e+02 | E | 科学计数法(大写 E) | println!("{:E}", 123.456) | 1.234560E+02 | g | 自动选择f或e(取较短形式) | println!("{:g}", 123456789.0) | 1.23457e+08 | G | 自动选择f或E | println!("{:G}", 123456789.0) | 1.23457E+08 |
通用与特殊类型
| 说明符 | 作用 | 适用场景 | 示例 | 输出结果 |
|---|
? | 按Debug trait 格式化(调试用) | 所有实现Debug 的类型 | println!("{:?}", vec![1,2]) | [1, 2] | #? | 美化的Debug格式(换行 + 缩进) | 复杂结构(如结构体、嵌套集合) | println!("{:#?}", vec![1,2]) | [\n 1,\n 2\n] | p | 指针地址 | 仅用于引用类型 | println!("{:p}", &10) | 0x7ff72194e7b8 |
标志(Flags)
特殊修饰符,用于调整输出格式,可与其他说明符组合使用。
| 标志 | 作用 | 示例 | 输出结果 |
|---|
# | 为数值添加前缀(二进制0b、八进制0o、十六进制0x) | println!("{:#x}", 255) | 0xff | + | 强制显示正负号(正数显+,负数显-) | println!("{:+}", 10);
println!("{:+}", -10) | +10
-10 | 0 | 用0填充(代替空格) | println!("{:05}", 123) | 00123 | _ | 为大数值添加千位分隔符(仅整数和浮点数) | println!("{:_}", 1000000) | 1_000_000 |
特殊格式
| 语法 | 示例 | 说明 |
|---|
{{ | {{ | 输出左花括号 { | }} | }} | 输出右花括号 } |
自定义Display获取参数
当在类型上实现 fmt::Display 时,可以在 fmt(&self, f: &mut fmt::Formatter<'_>) 中读取用户给的 width、precision、alternate 等:
use std::fmt;
struct Point { x: f64, y: f64 }
impl fmt::Display for Point {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// 获取 width / precision(Option<usize>)
if let Some(prec) = f.precision() {
write!(f, "({:.prec$}, {:.prec$})", self.x, self.y)
} else if f.alternate() {
// 如果用户写了 "{:#}",可切换格式
write!(f, "Point {{ x: {}, y: {} }}", self.x, self.y)
} else {
write!(f, "({}, {})", self.x, self.y)
}
}
}
到此这篇关于Rust中字符串与格式化操作方法的文章就介绍到这了,更多相关Rust字符串格式化内容请搜索琼殿技术社区以前的文章或继续浏览下面的相关文章希望大家以后多多支持琼殿技术社区!
您可能感兴趣的文章:- Rust字符串类型全解析(最新推荐)
- Rust中字符串String集合的具有使用
- Rust中字符串类型&str和String的使用
- Rust中字符串类型String的46种常用方法分享
- 利用Rust编写一个简单的字符串时钟
|