ZetCode

Rust 字符串

最后修改于 2025 年 2 月 19 日

在本文中,我们将展示如何在 Rust 中处理字符串。

在 Rust 中,字符串可以通过两种方式表示:字符串切片和拥有字符串。字符串切片(&str)是对字符串一部分的不可变引用。它通常用于借用的字符串数据,例如字符串字面量或 String 对象的一部分。字符串切片高效且轻量,因为它们不涉及数据复制,这使得它们非常适合只读操作。当将字符串作为函数参数传递时,通常会使用它们,以避免不必要的分配和复制。

另一方面,拥有字符串 String 是一种可增长、可变的字符串类型,它拥有其数据。它使用 String::from 等方法创建,并且可以通过追加字符或其他字符串来修改。String 类型适用于我们需要动态构建、修改或拥有字符串数据的场景。String 提供了各种操作方法,例如 pushpush_strconcatformat。理解 &strString 之间的区别对于编写高效且有效的 Rust 代码至关重要,因为每种类型根据上下文都有不同的用途。

创建字符串

在 Rust 中,字符串可以通过两种方式表示:字符串切片和拥有字符串。

main.rs
fn main() {
    let word1: &str = "falcon";
    let word2 = String::from("eagle");

    println!("{}", word1);
    println!("{}", word2);
}

在此示例中,我们有两个字符串:一个字符串切片和一个拥有字符串。

let word1: &str = "falcon";

此行创建了一个名为 word1 的字符串切片,值为“falcon”。字符串切片(&str)是对字符串一部分的引用,通常用于不可变字符串数据。

let world = String::from("eagle");

此行创建了一个名为 world 的 String 对象,值为“there!”。String 是 Rust 中一种可增长、可变的字符串类型,String::from 用于从字符串字面量创建 String。

λ cargo run -q
falcon
eagle

遍历字符

此示例演示了如何使用 chars 方法遍历 String 中的字符。

main.rs
fn main() {
    let phrase = String::from("an old falcon");

    for ch in phrase.chars() {
        println!("{}", ch);
    }
}

我们遍历 phrase 字符串中的每个字符并单独打印它们。

添加字符

Rust 字符串具有可用于操作字符串的各种方法。

main.rs
fn main() {
    let mut str = String::from("Hello, Rust");

    println!("Before: {}", str);
    str.push('!');
    println!("After: {}", str);
}

push 方法用于将字符添加到字符串的末尾。

λ cargo run -q
Before: Hello, Rust
After: Hello, Rust!

字符串连接

Rust 字符串可以使用 + 运算符和 format! 宏进行连接。

main.rs
fn main() {
    let s1 = String::from("an old");
    let s2 = String::from("falcon");

    let res = s1.clone() + " " + &s2; 
    println!("{}", res);

    let res = format!("{} {}", s1, s2);
    println!("{}", res);
}

该示例执行了两次连接操作。

let res = s1.clone() + " " + &s2; 
println!("{}", res);

s1.clone 创建了 s1 的副本,因为 + 运算符会获取其左侧字符串的所有权。" " 是一个字符串切片,用于在 s1s2 之间添加空格。&s2 是对 s2 的引用,允许 + 运算符在不获取所有权的情况下进行连接。结果字符串“an old falcon”被赋值给 resprintln!("{}", res) 打印连接后的字符串。

let res = format!("{} {}", s1, s2);
println!("{}", res);

format! 宏接受多个参数并将它们格式化为单个字符串。"{} {}" 是格式字符串,其中 {} 是变量 s1s2 的占位符。结果字符串 "an old falcon" 被赋值给 res

λ cargo run -q
an old falcon
an old falcon

字符串切片

此示例演示了如何从 String 创建字符串切片。

main.rs
fn main() {
    let phrase = String::from("an old falcon");

    let w1 = &phrase[3..6];
    let w2 = &phrase[7..13];

    println!("{}", w1);
    println!("{}", w2);
}

我们从 phrase 字符串创建切片 w1w2,提取“old”和“falcon”。

let w1 = &phrase[3..6];
let w2 = &phrase[7..13];

这些行从 phrase 字符串创建字符串切片 w1w2。在 Rust 中,字符串切片是对字符串一部分的引用,用语法 &[start..end] 表示,其中 start 是起始索引(包含),end 是结束索引(不包含)。

拆分字符串

split_whitespace 函数按空格拆分字符串切片。

main.rs
fn main() {
    let text = String::from("Rust is awesome!");

    let words: Vec<&str> = text.split_whitespace().collect();
    for word in words {
        println!("{}", word);
    }
}

text.split_whitespace 在每个空格字符处拆分 text 字符串,创建一个子字符串迭代器。collect 将这些子字符串收集到 Vec<&str> 中,即字符串切片向量。类型注解 Vec<&str> 明确指定向量包含字符串切片。

修剪空格

trim 方法会删除字符串开头和结尾的空格。

main.rs
fn main() {
    let text = String::from("\t\tan old falcon   ");

    println!("The string size: {}", text.len());

    let trimmed = text.trim();
    println!("Trimmed: '{}'", trimmed);

    println!("The string size: {}", text.len());
    println!("The string size: {}", trimmed.len());
}

我们从 text String 中删除空格字符。

let trimmed = text.trim();

trim 函数创建一个新的字符串切片(&str),该切片引用原始字符串中没有前导或尾随空格的部分。

λ cargo run -q
The string size: 18
Trimmed: 'an old falcon'
The string size: 18
The string size: 13

检查子字符串

如果给定模式匹配此字符串切片的子切片,则 contains 方法返回 true。

main.rs
fn main() {
    let text = String::from("Rust programming is fun.");

    // Check if the string contains a substring
    if text.contains("Rust") {
        println!("The text contains 'Rust'.");
    } else {
        println!("The text does not contain 'Rust'.");
    }
}

该示例检查 text 字符串是否包含单词“Rust”。

λ cargo run -q
The text contains 'Rust'.

作者

我的名字是 Jan Bodnar,我是一名充满热情的程序员,拥有丰富的编程经验。我从 2007 年开始撰写编程文章。至今,我已撰写了 1,400 多篇文章和 8 本电子书。我在教学编程方面拥有十多年的经验。

列出 所有 Rust 教程