
Rust 中的字符串:基础知识
Rust 提供了两种字符串类型:
1. &str
:字符串切片
- 它是什么:对字符串的引用------不可变的,通常来自字符串字面量。
- 它存储在哪里:作为指针和长度存储在栈上。
- 何时使用它:当你只需要读取字符串数据而不更改它时。
示例:
rust
let greeting: &str = "Hello, world!";
println!("Length of '{}': {}", greeting, greeting.len());
2. String
:拥有所有权的字符串
- 它是什么:一种可扩展的、在堆上分配的字符串,拥有其数据。
- 如何创建它 :使用
String::from()
或调用&str
上的.to_string()
。 - 何时使用它:当你需要修改内容或动态构建字符串时。
示例:
rust
let mut message = String::from("Hello");
message.push_str(", world!");
println!("Modified string: {}", message);
快速比较
特性 | &str |
String |
---|---|---|
所有权 | 借用 | 拥有 |
可变性 | 不可变 | 可变 |
内存 | 栈(引用) | 堆(数据) |
使用场景 | 只读访问 | 动态操作 |
关于 UTF-8 的说明
Rust 中的字符串采用 UTF-8 编码,这意味着它们支持所有语言的字符,甚至包括表情符号。但需要注意的是:
.len()
给出的是字节长度,而不是字符数量。- 要计算字符数量,请使用
.chars().count()
。
示例:
rust
let s = "olá";
println!("Bytes: {}, Characters: {}", s.len(), s.chars().count());
// 输出:字节:5,字符:3
字符串操作示例
现在开始动手实践。
示例 1:反转字符串
目标:反转字符串中的字符。
rust
pub fn reverse_string(input: &str) -> String {
input.chars().rev().collect()
}
fn main() {
let s = "Hello, Rust!";
let reversed = reverse_string(s);
println!("Original: '{}', Reversed: '{}'", s, reversed);
}
发生了什么:
- 我们将输入借用为
&str
。 - 使用
.chars()
获取字符迭代器(而不是字节)。 - 反转迭代器并收集到一个新的
String
中。
✅ 正确处理 Unicode 字符。
示例 2:向字符串追加文本
目标 :使用可变引用 String
添加后缀。
rust
pub fn add_suffix(s: &mut String, suffix: &str) {
s.push_str(suffix);
}
fn main() {
let mut name = String::from("Alice");
println!("Before: {}", name);
add_suffix(&mut name, " in Wonderland");
println!("After: {}", name);
}
为什么有效:
&mut String
给我们提供了可变访问权限。push_str()
将&str
添加到字符串末尾。- 无需返回任何内容------原始
String
已被更新。
示例 3:替换字符串中的部分内容
目标:将一个单词的所有实例替换为另一个单词。
rust
pub fn replace_text(input: &str, from: &str, to: &str) -> String {
input.replace(from, to)
}
fn main() {
let sentence = "I like to code in Rust, Rust is great!";
let new_sentence = replace_text(sentence, "Rust", "Python");
println!("Original: '{}'", sentence);
println!("Replaced: '{}'", new_sentence);
}
背后原理:
replace()
作用于&str
并返回一个新的String
。- 不会修改原始字符串------只是返回更新后的版本。
总结:完整程序示例
以下是结合所有内容的完整 Rust 程序:
rust
pub fn reverse_string(input: &str) -> String {
input.chars().rev().collect()
}
pub fn add_suffix(s: &mut String, suffix: &str) {
s.push_str(suffix);
}
pub fn replace_text(input: &str, from: &str, to: &str) -> String {
input.replace(from, to)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_reverse_string() {
assert_eq!(reverse_string("Hello"), "olleH");
}
#[test]
fn test_add_suffix() {
let mut s = String::from("Hello");
add_suffix(&mut s, "!");
assert_eq!(s, "Hello!");
}
#[test]
fn test_replace_text() {
assert_eq!(replace_text("cat cat", "cat", "dog"), "dog dog");
}
}
fn main() {
// 反转
let s1 = "Rust";
println!("Reversed: '{}'", reverse_string(s1));
// 追加
let mut s2 = String::from("Rust");
add_suffix(&mut s2, " is fun");
println!("Appended: '{}'", s2);
// 替换
let s3 = "Rust Rust";
println!("Replaced: '{}'", replace_text(s3, "Rust", "Code"));
}
运行它:
arduino
cargo run
进入全屏模式退出全屏模式
输出:
vbnet
Reversed: 'tsuR'
Appended: 'Rust is fun'
Replaced: 'Code Code'
最后的思考
- 在读取或传递字符串时使用
&str
。 - 当你需要所有权或想要修改数据时使用
String
。 - 始终以 Rust 的借用和所有权模型来思考。
- 记住
.len()
给出的是字节长度------在处理 Unicode 时使用.chars()
。