0x0 概述
-
#[derive(PartialEq, PartialOrd, Eq, Ord)]
:这一行是 Rust 的属性(Attribute)语法,用于自动实现一些 trait。在这里,derive
属性指示编译器自动为String
类型实现PartialEq
、PartialOrd
、Eq
和Ord
这四个 trait。这使得String
类型可以进行相等性比较和排序操作。 -
#[stable(feature = "rust1", since = "1.0.0")]
:这是另一个属性,用于指示该结构体的稳定性。stable
属性表明这个结构体是在 Rust 1.0.0 版本中引入的,并且是稳定的,即其 API 不会轻易改变。 -
#[cfg_attr(not(test), lang = "String")]
:这是一个条件属性,用于根据编译时的条件来设置属性。在这里,cfg_attr
属性指示在非测试环境下,为String
类型设置lang = "String"
。这可能是为了指定String
类型的语言特性或行为。 -
pub struct String { vec: Vec<u8>, }
:这是定义了一个公共(pub
)的结构体String
,它包含一个字段vec
,类型为Vec<u8>
。这表明String
类型实际上是基于Vec<u8>
实现的,即字符串在内部以字节序列的形式存储。
String
是个结构体,并利用 Vec<u8>
存储字符串的字节序列,并且通过属性指示实现了相等性比较、排序等 trait。
0x1 字符串类型
在 Rust 中,有两种主要的字符串类型:&str
和 String
。它们分别代表着不同的字符串存储方式和特性。
-
&str
:字符串切片类型,通常用于引用字符串数据的不可变视图。&str
是一个不可变的引用,它指向存储在其他地方的字符串数据。&str
通常用于函数参数、字符串切片操作和字符串的读取操作。 -
String
:字符串类型,代表一个可变、可增长、UTF-8 编码的字符串。String
类型是基于堆内存分配的,可以动态地分配和释放内存,支持各种字符串操作和方法。String
类型通常用于需要动态创建、修改和拥有字符串数据的场景。
fn main() {
// 使用 &str 类型
let s1: &str = "Hello, Rust!"; // 字符串字面量是 &str 类型
let s2: &str = "Hello, Word"; // 字符串字面量是 &str 类型
// 使用 String 类型
let mut string1 = String::from("Hello, ");
string1.push_str("Rust!"); // 向字符串末尾追加一个字符串切片
println!("{}", s1);
println!("{}", string1);
}
在这个示例中,我们使用了字符串字面量创建了两个 &str
类型的字符串切片,以及使用 String::from
创建了一个 String
类型的可变字符串。通过这两种类型,Rust 提供了灵活的字符串处理能力,可以满足不同场景下的需求。
&str
适合于引用和操作已有的字符串数据,而 String
适合于动态创建、拥有和修改字符串数据。
str 是 Rust 中的原始字符串数据类型(primitive string type),通常以引用形式 &str 出现,表示字符串切片。
0x2 创建字符串的方式
在 Rust 中,你可以使用两种主要的方式来创建字符串:
1. 使用 String
类型:String
类型是一个可变的、拥有所有权的字符串类型。你可以通过 String::from
函数或者直接使用字符串字面量和 to_string
方法来创建 String
类型的字符串。
// 使用 String::from 函数创建 String 类型的字符串
let s1 = String::from("hello");
// 使用 to_string 方法创建 String 类型的字符串
let s2 = "world".to_string();
2. 使用字符串切片 &str
:字符串切片 &str
表示不可变的字符串数据的引用。你可以使用字符串字面量直接创建字符串切片。
// 使用字符串字面量创建字符串切片
let s = "hello";
//使用 to_string 方法将字符串字面量转换为 String 对象
let s1 = "hello".to_string();
这些方法都提供了灵活的方式来创建不同类型的字符串,你可以根据具体的需求选择合适的方式来创建和操作字符串。
3.使用String::new
方法用于创建一个新的空字符串对象
let mut s = String::new();
4.使用 format! 宏来创建一个 String 对象
let s = format!("The answer is {}", 42);
5.使用 + 运算符或者 format! 宏来拼接多个字符串
let s1 = String::from("hello");
let s2 = "world".to_string();
let s3 = s1 + " " + &s2;
6.使用 String::from_utf8 方法从字节数组创建 String 对象
let bytes = vec![104, 101, 108, 108, 111]; // ASCII 编码的 "hello"
let s = String::from_utf8(bytes).unwrap();
0x3 String常用方法
String
类型是 Rust 标准库中用于表示可变的、拥有所有权的字符串的类型。String
类型提供了许多方法来操作字符串数据。以下是 String
类型的一些常用方法:
1. new
:创建一个新的空字符串。
let mut s = String::new();
2. from
:从字符串字面量创建一个 String
对象。
let s = String::from("hello");
3. push_str
:向字符串末尾追加一个字符串切片。
let mut s = String::from("hello");
s.push_str(", world!");
4. push
:向字符串末尾追加一个字符。
let mut s = String::from("hello");
s.push('!');
5. pop
:移除并返回末尾的字符。
let mut s = String::from("hello");
let popped = s.pop();
6. replace
:替换字符串中的子串。
let s = String::from("hello, world!");
let new_s = s.replace("hello", "hi");
7. len
:返回字符串的长度(以字节为单位)。
let s = String::from("hello");
let len = s.len();
8. is_empty
:检查字符串是否为空。
let s = String::from("hello");
let is_empty = s.is_empty();
9. contains
:检查字符串是否包含指定的子串。
let s = String::from("hello, world!");
let contains_world = s.contains("world");
10. split
:根据指定的分隔符拆分字符串为迭代器。
let s = String::from("apple,orange,banana");
let parts: Vec<&str> = s.split(",").collect();
11. to_uppercase
和 to_lowercase
:将字符串转换为全大写或全小写。
let s = String::from("hello");
let upper = s.to_uppercase();
let lower = s.to_lowercase();
12. trim
、trim_start
和 trim_end
:移除字符串两端、开头或结尾的空白字符。
let s = String::from(" hello ");
let trimmed = s.trim();
let trimmed_start = s.trim_start();
let trimmed_end = s.trim_end();
13. split_whitespace
:根据空白字符(空格、制表符等)拆分字符串为迭代器。
let s = String::from("hello world");
let parts: Vec<&str> = s.split_whitespace().collect();
14. chars
:返回字符串中每个字符的迭代器。
let s = String::from("hello");
let chars: Vec<char> = s.chars().collect();
15. as_str
:将 String
转换为不可变的字符串切片 &str
。
let s = String::from("hello");
let str_slice: &str = s.as_str();
16. capacity
:返回字符串的容量。
let s = String::with_capacity(10);
let capacity = s.capacity();
17. shrink_to_fit
:收缩字符串的容量,使其等于其长度。
let mut s = String::with_capacity(10);
s.push_str("hello");
s.shrink_to_fit();
18. split_at
:在指定索引处拆分字符串为两部分。
let s = String::from("hello");
let (first, second) = s.split_at(3);
19. starts_with
和 ends_with
:检查字符串是否以指定的前缀或后缀开头。
let s = String::from("hello");
let starts_with_h = s.starts_with("h");
let ends_with_o = s.ends_with("o");
20. repeat
:重复字符串多次。
let s = String::from("hello");
let repeated = s.repeat(3);
21. replace_range
:替换指定范围内的子串。
let mut s = String::from("hello");
s.replace_range(1..4, "i");
22. insert_str
:在指定索引处插入字符串。
let mut s = String::from("hello");
s.insert_str(2, "123");
23. drain
:移除指定范围内的字符,并返回一个迭代器。
let mut s = String::from("hello");
let removed: String = s.drain(1..4).collect();
24. split
和 splitn
:根据指定的分隔符拆分字符串为迭代器,splitn
可以限制拆分的次数。
let s = String::from("apple,banana,cherry,date");
let parts: Vec<&str> = s.split(",").collect();
let limited_parts: Vec<&str> = s.splitn(2, ",").collect();
25. lines
:将字符串按行拆分为迭代器。
let s = String::from("apple\nbanana\ncherry\ndate");
let lines: Vec<&str> = s.lines().collect();
26. matches
:返回一个迭代器,产生所有与给定模式匹配的子串。
let s = String::from("a1b2c3d4");
let digits: Vec<&str> = s.matches(char::is_numeric).collect();
27. is_empty
:检查字符串是否为空。
let s1 = String::from("");
let s2 = String::from("hello");
let is_empty1 = s1.is_empty();
let is_empty2 = s2.is_empty();