Rust主要有两种类型的字符串:&str和String
由&[u8]表示,UTF-8编码的字符串的引用,字符串字面值,也称作字符串切片。&str用于查看字符串中的数据。它的大小是固定的,即它不能调整大小。
String 类型来自标准库,它是可修改、可变长度、可拥有所有权的同样使用UTF-8编码,且它不以空(null)值终止,实际上就是对Vec
其源代码大致如下:
pub struct String { vec: Vec, } impl String { pub fn new() -> String { String { vec: Vec::new() } } pub fn with_capacity(capacity: usize) -> String { String { vec: Vec::with_capacity(capacity) } } pub fn push(&mut self, ch: char) { // ... } pub fn push_str(&mut self, string: &str) { // ... } pub fn clear(&mut self) { self.vec.clear(); } pub fn capacity(&self) -> usize { self.vec.capacity() } pub fn reserve(&mut self, additional: usize) { self.vec.reserve(additional); } pub fn reserve_exact(&mut self, additional: usize) { self.vec.reserve_exact(additional); } pub fn shrink_to_fit(&mut self) { self.vec.shrink_to_fit(); } pub fn into_bytes(self) -> Vec { self.vec } pub fn as_str(&self) -> &str { // ... } pub fn len(&self) -> usize { // ... } pub fn is_empty(&self) -> bool { self.len() == 0 } pub fn from_utf8(vec: Vec ) -> Result { // ... } pub fn from_utf8_lossy<'a>(v: &'a [u8]) -> Cow<'a, str> { // ... } } impl Clone for String { fn clone(&self) -> String { String { vec: self.vec.clone() } } fn clone_from(&mut self, source: &Self) { self.vec.clone_from(&source.vec); } } impl fmt::Display for String { // ... } impl fmt::Debug for String { // ... } impl PartialEq for String { // ... } impl Eq for String { // ... } impl PartialOrd for String { // ... } impl Ord for String { // ... } impl Hash for String { // ... } impl AsRef for String { // ... } impl AsRef<[u8]> for String { // ... } impl From<&str> for String { // ... } impl From for Vec { // ... } // ...
String是一个可变引用,而&str是对该字符串的不可变引用,即可以更改String的数据,但是不能操作&str的数据。String包含其数据的所有权,而&str没有所有权,它从另一个变量借用得来。
Rust 的标准库中还包含其他很多字符串类型,例如:OsString、OsStr、CString、CStr。
1、使用String::new创建空的字符串。
let empty_string = String::new();
2、使用String::from通过字符串字面量创建字符串。实际上复制了一个新的字符串。
let rust_str = "rust";
let rust_string = String::from(rust_str);
3、使用字符串字面量的to_string将字符串字面量转换为字符串。实际上复制了一个新的字符串。
let s1 = "rust_to_string";
let s2 = s1.to_string();
to_string()实际上是封装了String::from()
4、使用{}格式化输出
let s = "rust";
print!("{}",s);
1、String字符串是UTF-8编码,不提供索引操作。
2、Rust 使用切片来“索引”字符串,[ ] 里不是单个数字而是必须要提供范围。
范围操作符: .. 或 ..=
start..end 左开右闭区间 [start, end)
start..=end 全开区间 [start, end]
示例:
fn main() { let s = "hello, world"; let a = &s[1..4]; println!("{}", a); let a = &s[1..=4]; println!("{}", a); //单个字符只能使用范围指定,不能仅用一个整数[1] let a = &s[1..2]; println!("{}", a); let a = &s[1..=1]; println!("{}", a); //等价于以下操作: println!("{:?}", s.chars().nth(1)); println!("{}", s.chars().nth(1).unwrap()); }
输出:
ell
ello
e
e
Some('e')
e
fn main() { let s1 = String::from("hello"); let s2 = String::from("world"); let s = s1 + ", " + &s2 ; println!("{}", s); }
输出:
hello, world
.chars()方法:该方法返回一个迭代器,可以遍历字符串的Unicode字符。
let s = String::from("Hello, Rust!"); for c in s.chars() { println!("{}", c); }
.bytes()方法:该方法返回一个迭代器,可以遍历字符串的字节序列。
let s = String::from("Hello, Rust!"); for b in s.bytes() { println!("{}", b); }
.chars().enumerate()方法:该方法返回一个元组迭代器,可以同时遍历字符和它们在字符串中的索引。
let s = String::from("Hello, Rust!"); for (i, c) in s.chars().enumerate() { println!("{}: {}", i, c); }
.split()方法:该方法返回一个分割迭代器,可以根据指定的分隔符将字符串分割成多个子字符串,然后遍历每个子字符串。
let s = String::from("apple,banana,orange"); for word in s.split(",") { println!("{}", word); }
.split_whitespace()方法:该方法返回一个分割迭代器,可以根据空格将字符串分割成多个子字符串,然后遍历每个子字符串。
let s = String::from("The quick brown fox"); for word in s.split_whitespace() { println!("{}", word); }
fn main() { let s = String::from("The quick brown fox"); let mut i = 0; while i < s.len() { print!("{}", &s[i..=i]); i += 1; } println!(); while i > 0 { i -= 1; print!("{}", &s[i..=i]); } println!(); loop { if i >= s.len() { break; } print!("{}", &s[i..i+1]); i += 1; } println!(); }ox
输出:
The quick brown fox
xof nworb kciuq ehT
The quick brown fox
String除了以上这几种最基本的操作外,标准库提供了删增改等等各种各样的方法以方便程序员用来操作字符串。以下归纳了String字符串比较常用的46种方法:
new():创建一个空的 String 对象。
let s = String::new();
from():从一个字符串字面量、一个字节数组或另一个字符串对象中创建一个新的 String 对象。
let s1 = String::from("hello");
let s2 = String::from_utf8(vec![104, 101, 108, 108, 111]).unwrap();
let s3 = String::from(s1);
with_capacity():创建一个具有指定容量的 String 对象。
let mut s = String::with_capacity(10);
s.push('a');
capacity():返回字符串的容量(以字节为单位)。
let s = String::with_capacity(10);
assert_eq!(s.capacity(), 10);
reserve():为字符串预留更多的空间。
let mut s = String::with_capacity(10);
s.reserve(10);
shrink_to_fit():将字符串的容量缩小到它所包含的内容所需的最小值。
let mut s = String::from("foo");
s.reserve(100);
assert!(s.capacity() >= 100);
s.shrink_to_fit();
assert_eq!(3, s.capacity());
shrink_to():将字符串的容量缩小到指定下限。如果当前容量小于下限,则这是一个空操作。
let mut s = String::from("foo");
s.reserve(100);
assert!(s.capacity() >= 100);
s.shrink_to(10);
assert!(s.capacity() >= 10);
s.shrink_to(0);
assert!(s.capacity() >= 3);
push():将一个字符追加到字符串的末尾。
let mut s = String::from("hello");
s.push('!');
push_str():将一个字符串追加到字符串的末尾。
let mut s = String::from("hello");
s.push_str(", world!");
pop():将字符串的最后一个字符弹出,并返回它。
let mut s = String::from("hello");
let last = s.pop();
truncate():将字符串截短到指定长度,此方法对字符串的分配容量没有影响。
let mut s = String::from("hello");
s.truncate(2);
assert_eq!("he", s);
assert_eq!(2, s.len());
assert_eq!(5, s.capacity());
clear():将字符串清空,此方法对字符串的分配容量没有影响。
let mut s = String::from("foo");
s.clear();
assert!(s.is_empty());
assert_eq!(0, s.len());
assert_eq!(3, s.capacity());
remove():从字符串的指定位置移除一个字符,并返回它。
let mut s = String::from("hello");
let second = s.remove(1);
remove_range():从字符串的指定范围删除所有字符。
let mut s = String::from("hello");
s.remove_range(1..3);
insert():在字符串的指定位置插入一个字符。
let mut s = String::from("hello");
s.insert(2, 'l');
insert_str():在字符串的指定位置插入一个字符串。
let mut s = String::from("hello");
s.insert_str(2, "ll");
replace():将字符串中的所有匹配项替换为另一个字符串。
let mut s = String::from("hello, world");
let new_s = s.replace("world", "Rust");
replace_range():替换字符串的指定范围内的所有字符为另一个字符串。
let mut s = String::from("hello");
s.replace_range(1..3, "a");
split():将字符串分割为一个迭代器,每个元素都是一个子字符串。
let s = String::from("hello, world");
let mut iter = s.split(", ");
assert_eq!(iter.next(), Some("hello"));
assert_eq!(iter.next(), Some("world"));
assert_eq!(iter.next(), None);
split_whitespace():将字符串分割为一个迭代器,每个元素都是一个不包含空格的子字符串。
let s = String::from(" hello world ");
let mut iter = s.split_whitespace();
assert_eq!(iter.next(), Some("hello"));
assert_eq!(iter.next(), Some("world"));
assert_eq!(iter.next(), None);
split_at():将字符串分成两个部分,在指定的位置进行分割。
let s = String::from("hello");
let (left, right) = s.split_at(2);
split_off():从字符串的指定位置分离出一个子字符串,并返回新的 String 对象。
let mut s = String::from("hello");
let new_s = s.split_off(2);
len():返回字符串的长度(以字节为单位)。
let s = String::from("hello");
assert_eq!(s.len(), 5);
is_empty():检查字符串是否为空。
let s = String::from("");
assert!(s.is_empty());
as_bytes():将 String 对象转换为字节数组。
let s = String::from("hello");
let bytes = s.as_bytes();
into_bytes():将 String 对象转换为字节向量。
let s = String::from("hello");
let bytes = s.into_bytes();
assert_eq!(&[104, 101, 108, 108, 111][..], &bytes[..]);
clone():创建一个与原始字符串相同的新字符串。
let s1 = String::from("hello");
let s2 = s1.clone();
eq():比较两个字符串是否相等。
let s1 = String::from("hello");
let s2 = String::from("hello");
assert!(s1.eq(&s2));
contains():检查字符串是否包含指定的子字符串。
let s = String::from("hello");
assert!(s.contains("ell"));
starts_with():检查字符串是否以指定的前缀开头。
let s = String::from("hello");
assert!(s.starts_with("he"));
ends_with():检查字符串是否以指定的后缀结尾。
let s = String::from("hello");
assert!(s.ends_with("lo"));
find():查找字符串中第一个匹配指定子字符串的位置。
let s = String::from("hello");
let pos = s.find("l");
assert_eq!(pos, Some(2));
rfind():查找字符串中最后一个匹配指定子字符串的位置。
let s = String::from("hello");
let pos = s.rfind("l");
assert_eq!(pos, Some(3));
trim():删除字符串两端的所有空格。
let s = String::from(" hello ");
let trimmed = s.trim();
trim_start():删除字符串开头的所有空格。
let s = String::from(" hello ");
let trimmed = s.trim_start();
trim_end():删除字符串末尾的所有空格。
let s = String::from(" hello ");
let trimmed = s.trim_end();
to_lowercase():将字符串中的所有字符转换为小写。
let s = String::from("HeLLo");
let lower = s.to_lowercase();
to_uppercase():将字符串中的所有字符转换为大写。
let s = String::from("HeLLo");
let upper = s.to_uppercase();
retain():保留满足指定条件的所有字符。
let mut s = String::from("hello");
s.retain(|c| c != 'l');
drain():从字符串中删除指定范围内的所有字符,并返回它们的迭代器。
let mut s = String::from("hello");
let mut iter = s.drain(1..3);
assert_eq!(iter.next(), Some('e'));
assert_eq!(iter.next(), Some('l'));
assert_eq!(iter.next(), None);
lines():将字符串分割为一个迭代器,每个元素都是一行文本。
let s = String::from("hello\nworld");
let mut iter = s.lines();
assert_eq!(iter.next(), Some("hello"));
assert_eq!(iter.next(), Some("world"));
assert_eq!(iter.next(), None);
chars():将字符串分割为一个迭代器,每个元素都是一个字符。
let s = String::from("hello");
let mut iter = s.chars();
assert_eq!(iter.next(), Some('h'));
assert_eq!(iter.next(), Some('e'));
assert_eq!(iter.next(), Some('l'));
assert_eq!(iter.next(), Some('l'));
assert_eq!(iter.next(), Some('o'));
assert_eq!(iter.next(), None);
bytes():将字符串分割为一个迭代器,每个元素都是一个字节。
let s = String::from("hello");
let mut iter = s.bytes();
assert_eq!(iter.next(), Some(104));
assert_eq!(iter.next(), Some(101));
assert_eq!(iter.next(), Some(108));
assert_eq!(iter.next(), Some(108));
assert_eq!(iter.next(), Some(111));
assert_eq!(iter.next(), None);
as_str():将 String 对象转换为字符串切片。
let s = String::from("hello");
let slice = s.as_str();
as_mut_str():将 String 对象转换为可变字符串切片。
let mut s = String::from("foobar");
let s_mut_str = s.as_mut_str();
s_mut_str.make_ascii_uppercase();
assert_eq!("FOOBAR", s_mut_str);
remove_matches():删除字符串中所有匹配的子串。
#![feature(string_remove_matches)] //使用不稳定的库功能,此行必须
let mut s = String::from("Trees are not green, the sky is not blue.");
s.remove_matches("not ");
assert_eq!("Trees are green, the sky is blue.", s);
String字符串包括但不限于此46种方法,更多方法请见官方文档:
String in std::string - Rust