当前位置: 首页 > news >正文

趣味学RUST基础篇(String)

String:Rust 里的“魔法卷轴”!

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

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

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

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

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

首先:什么是“字符串”?

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

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

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

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

创建一个“魔法卷轴”

方法一:空卷轴启动!

let mut s = String::new();

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


方法二:从文字变卷轴!

let data = "初始内容";
let s = data.to_string();  // 变!

或者更直接:

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

to_string() 还是 String::from()
随你喜欢!就像“番茄炒蛋”和“蛋炒番茄”,看你心情!


它支持所有语言!

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

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

统统支持!

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

1. 用 push_str 添加文字

let mut s = String::from("Hello");
s.push_str(", world!");

现在 s"Hello, world!"

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

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

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


2. 用 push 添加单个字符

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

结果:"lol"

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

方法一:用 +

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! 宏 —— 推荐!

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

let s = s1 + "-" + &s2 + "-" + &s3;  // 眼都花了!

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

let s = format!("{}-{}-{}", s1, s2, s3);

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


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

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

s = "hello"
print(s[0])  # 'h'

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

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

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

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

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

比如:

let hello = String::from("Hola");

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

但如果是:

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

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

所以,如果你写:

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

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

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


三种看字符串的方式

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

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

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


遍历字符串:推荐方式

遍历每个字符:

for c in "नमस्ते".chars() {println!("{c}");
}

遍历每个字节:

for b in "नमस्ते".bytes() {println!("{b}");
}

想要“字形簇”?标准库没给,但你可以在 crates.io 找 unicode-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 没有隐藏这种复杂性,而是把它摆在你面前,让你写出真正健壮的代码。

http://www.xdnf.cn/news/1417915.html

相关文章:

  • rust语言 (1.88) egui (0.32.1) 学习笔记(逐行注释)(二十二)控件的可见、可用性
  • 如何从 STiROT 启动 STiROT_Appli_TrustZone LAT1556
  • JS闭包讲解
  • Elasticsearch面试精讲 Day 4:集群发现与节点角色
  • 《JAVA EE企业级应用开发》第一课笔记
  • 记录第一次使用docker打包镜像的操作步骤以及问题解决
  • 初识JVM
  • Personality Test 2025
  • 正则表达式与grep文本过滤详解
  • 【C++游记】AVL树
  • 刷题日记0901
  • (3dnr)多帧视频图像去噪 (二)
  • MySQL内置的各种单行函数
  • 强化学习实战:从零搭建自主移动机器人避障仿真(1)— 导论篇
  • 【LeetCode热题100道笔记+动画】乘积最大子数组
  • AI+PLM如何重构特种/高端复杂装备行业的工艺管理?
  • 再见 K8s!3款开源的云原生部署工具
  • 开源模型应用落地-模型上下文协议(MCP)-为AI智能体打造的“万能转接头”-“mcp-use”(十二)
  • [开源项目] Tiny-RAG :一套功能完善、高度可配的本地知识库问答解决方案
  • 深度学习篇---ShuffleNet网络结构
  • 广电手机卡到底好不好?
  • 科学研究系统性思维的方法体系:数据收集
  • 【Audio】切换至静音或振动模式时媒体音自动置 0
  • docker安装redis,进入命令窗口基操练习命令
  • 优化括号匹配检查:从Stack到计数器的性能提升
  • MOS管学习
  • Linux 进程状态 — 僵尸进程
  • FDTD_梯度波导学习(1)
  • HOW - 前端团队产出评定方案参考
  • 携程旅行 web 验证码 分析