趣味学RUST基础篇(String)

String:Rust 里的"魔法卷轴"!

在前面的内容,我们学会了用 Vec<T> 装整数、装枚举,像个收纳高手。

但作为冒险者,你总得写点日记吧?比如:

"今日击败恶龙,获得金币 ×100,太棒了"

这就需要一个能装文字 的容器------在 Rust 里,它就是 String

但别被名字骗了,String 可不是简单的"一串字符"。它是个会魔法的卷轴,能装中文、阿拉伯文、俄文、emoji......\但正因为太强大,它也比你想象的复杂得多。接下来,我们揭开它的神秘面纱!

首先:什么是"字符串"?

在 Rust 世界里,有两种"文字":

类型 名字 特点
&str 字符串切片 "只读卷轴",通常来自字面量,比如 "hello"
String 动态字符串 "可编辑卷轴",能增、删、改,像 Vec<T> 一样灵活

通常我们说"字符串",就是指这两个一起。

其他语言可能把它们混为一谈,但 Rust 很认真:"只读"和"可变"是两回事!

创建一个"魔法卷轴"

方法一:空卷轴启动!

rust 复制代码
let mut s = String::new();

就像买了一张空白羊皮纸,等着你写点什么。


方法二:从文字变卷轴!

rust 复制代码
let data = "初始内容";
let s = data.to_string();  // 变!

或者更直接:

rust 复制代码
let s = "初始内容".to_string();
let s = String::from("初始内容");  // 效果一样!

to_string() 还是 String::from()

随你喜欢!就像"番茄炒蛋"和"蛋炒番茄",看你心情!


它支持所有语言!

StringUTF-8 编码的,所以你可以写:

rust 复制代码
let 你好 = String::from("你好");
let привет = String::from("Здравствуйте");
let 안녕 = String::from("안녕하세요");
let 😎 = String::from("今天真棒!");

统统支持!

更新字符串:往卷轴上写字!

1. 用 push_str 添加文字

rust 复制代码
let mut s = String::from("Hello");
s.push_str(", world!");

现在 s"Hello, world!"

有趣的是:push_str 接收的是 &str(字符串切片),所以它不拿走所有权

rust 复制代码
let mut s1 = String::from("foo");
let s2 = "bar";
s1.push_str(s2);
println!("s2 还能用:{s2}");  // 正常打印!

Rust 很贴心,不会偷偷把你的字符串"吃掉"。


2. 用 push 添加单个字符

rust 复制代码
let mut s = String::from("lo");
s.push('l');  // 注意是单引号!

结果:"lol"

# 拼接字符串:把多个卷轴合成一个!

方法一:用 +

rust 复制代码
let s1 = String::from("Hello, ");
let s2 = String::from("world!");
let s3 = s1 + &s2;  // 注意:&s2 是引用

结果是 "Hello, world!"

但注意:s1 被"吃掉"了!

你不能再用 s1,因为它已经被移动到 s3 里了。

原理:+ 其实调用了 add(self, &str),它拿走了 self 的所有权。

所以这行代码其实是:

  • 拿走 s1
  • s2 的内容复制进来
  • 返回一个全新的 String

虽然写起来像拼积木,但背后是"拆了旧的,建个新的"。


方法二:用 format! 宏 ------ 推荐!

如果你要拼接多个字符串,+ 就太难看了:

rust 复制代码
let s = s1 + "-" + &s2 + "-" + &s3;  // 眼都花了!

这时,用 format! 宏,优雅又安全:

rust 复制代码
let s = format!("{}-{}-{}", s1, s2, s3);

不获取所有权、 代码清晰、 性能好, 就像 println!,但不打印,而是返回一个 String


不能用索引?s[0] 为什么不行?

在 Python、JavaScript 里,你可能习惯这么写:

python 复制代码
s = "hello"
print(s[0])  # 'h'

但在 Rust,这样写会编译失败

rust 复制代码
let s = String::from("hello");
let h = s[0];  // 编译错误!

为什么?因为 String 在 Rust 里不是"字符数组"那么简单!

🔍 深入魔法:String 到底怎么存的?

String 本质是 Vec<u8> ------ 一串字节

比如:

rust 复制代码
let hello = String::from("Hola");

它在内存里是:[72, 111, 108, 97] ------ 4 个字节。

但如果是:

rust 复制代码
let hello = String::from("Здравствуйте");

这 12 个西里尔字母,却占了 24 个字节!因为每个字母用 2 字节 UTF-8 编码。

所以,如果你写:

rust 复制代码
let s = &hello[0..1];  // 只取第一个字节?

你会得到一个不完整的字节序列,根本不是合法字符!

Rust 宁愿让你编译失败,也不让你写出"看似正确实则乱码"的代码。


三种看字符串的方式

Rust 让你明确选择:你想怎么"读"字符串?

方式 方法 例子("नमस्ते")
字节 .bytes() 18 个字节 [224, 164, ...]
字符(Unicode 标量值) .chars() 6 个 char'न', 'म', 'स', '्', 'त', 'े'
字形簇(视觉上的"字") 需要外部库 4 个:"न", "म", "स्", "ते"

.chars() 最常用,但注意:像 这种是"变音符号",单独没意义。


遍历字符串:推荐方式

遍历每个字符:

rust 复制代码
for c in "नमस्ते".chars() {
    println!("{c}");
}

遍历每个字节:

rust 复制代码
for b in "नमस्ते".bytes() {
    println!("{b}");
}

想要"字形簇"?标准库没给,但你可以在 crates.iounicode-segmentation 这样的库。

为什么 Rust 要这么复杂?

因为:

"简单"往往藏着陷阱。

其他语言让你用 s[0],但遇到中文、emoji 时,可能返回乱码或半个字符。

Rust 说:

"我宁可你现在觉得麻烦,也别将来在生产环境炸了服务器。"

所以它强制你思考:

  • 我要的是字节?字符?还是视觉上的"字"?
  • 我的代码是否真正理解 UTF-8?

#String 使用口诀

操作 推荐方式
创建 String::from("...")"...".to_string()
拼接 format!("{} {}", s1, s2)(安全又清晰)
添加 push_str()(加字符串)、push()(加字符)
遍历 .chars()(最常用)或 .bytes()
切片 &s[0..4](必须按字节,小心越界!)
索引 不支持!用 .chars().nth(0) 代替(但性能差)

总结:

字符串,远比你想象的复杂。

Rust 没有隐藏这种复杂性,而是把它摆在你面前,让你写出真正健壮的代码。

相关推荐
咸甜适中10 小时前
rust语言 (1.88) egui (0.32.1) 学习笔记(逐行注释)(二十三)控件中常用文本格式
笔记·学习·rust·egui
bobz96510 小时前
什么是 ebpf
后端
编码浪子10 小时前
趣味学RUST基础篇(HashMap)
开发语言·后端·rust
SimonKing10 小时前
弃用MinIO,拥抱全新一代分布式文件系统RustFS
java·后端·程序员
eqwaak010 小时前
科技信息差(9.2)
开发语言·人工智能·科技·华为·语言模型·开源
明月醉窗台10 小时前
Qt Demo(3) 之 deepseek 帮我写的关于图像显示的小界面
开发语言·人工智能·windows·qt
银二码10 小时前
flutter踩坑插件:Swift架构不兼容
开发语言·flutter·swift
AAA修煤气灶刘哥10 小时前
后端人必看!配置中心这玩意儿,用 Nacos 玩明白能少熬 3 个夜
java·后端·spring cloud
一蓑烟雨,一任平生10 小时前
h5实现内嵌微信小程序&支付宝 --截图保存海报分享功能
开发语言·前端·javascript