Rust 标准库字符串类型String及其46种常用方法

news2024/11/20 18:24:47

Rust字符串

Rust主要有两种类型的字符串:&str和String

&str

由&[u8]表示,UTF-8编码的字符串的引用,字符串字面值,也称作字符串切片。&str用于查看字符串中的数据。它的大小是固定的,即它不能调整大小。

String

String 类型来自标准库,它是可修改、可变长度、可拥有所有权的同样使用UTF-8编码,且它不以空(null)值终止,实际上就是对Vec<u8>的包装,在堆内存上分配一个字符串。

其源代码大致如下:

pub struct String {
    vec: Vec<u8>,
}
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<u8> {
        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<u8>) -> Result<String, FromUtf8Error> {
        // ...
    }
    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<str> for String {
    // ...
}
impl AsRef<[u8]> for String {
    // ...
}
impl From<&str> for String {
    // ...
}
impl From<String> for Vec<u8> {
    // ...
}
// ...

String 和 &str 的区别

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

拼接和迭代

1、拼接直接使用加号 +

fn main() {
    let s1 = String::from("hello");
    let s2 = String::from("world");
 
    let s = s1 + ", " + &s2 ;
    
    println!("{}", s);
}

输出: 

hello, world

2、各种遍历(迭代)

.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); 
}

3. 使用切片循环输出

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种方法:

String 方法

1. new

new():创建一个空的 String 对象。

let s = String::new();

2. from

from():从一个字符串字面量、一个字节数组或另一个字符串对象中创建一个新的 String 对象。

let s1 = String::from("hello");
let s2 = String::from_utf8(vec![104, 101, 108, 108, 111]).unwrap();
let s3 = String::from(s1);

3. with_capacity

with_capacity():创建一个具有指定容量的 String 对象。

let mut s = String::with_capacity(10);
s.push('a');

4. capacity

capacity():返回字符串的容量(以字节为单位)。

let s = String::with_capacity(10);
assert_eq!(s.capacity(), 10);

5. reserve

reserve():为字符串预留更多的空间。

let mut s = String::with_capacity(10);
s.reserve(10);

6. shrink_to_fit

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());

7. shrink_to

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);

8. push

push():将一个字符追加到字符串的末尾。

let mut s = String::from("hello");
s.push('!');

9. push_str

push_str():将一个字符串追加到字符串的末尾。

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

10. pop

pop():将字符串的最后一个字符弹出,并返回它。

let mut s = String::from("hello");
let last = s.pop();

11. truncate

truncate():将字符串截短到指定长度,此方法对字符串的分配容量没有影响。

let mut s = String::from("hello");
s.truncate(2);
assert_eq!("he", s);
assert_eq!(2, s.len());
assert_eq!(5, s.capacity());

12. clear

clear():将字符串清空,此方法对字符串的分配容量没有影响。

let mut s = String::from("foo");
s.clear();
assert!(s.is_empty());
assert_eq!(0, s.len());
assert_eq!(3, s.capacity());

13. remove

remove():从字符串的指定位置移除一个字符,并返回它。

let mut s = String::from("hello");
let second = s.remove(1);

14. remove_range

remove_range():从字符串的指定范围删除所有字符。

let mut s = String::from("hello");
s.remove_range(1..3);

15. insert

insert():在字符串的指定位置插入一个字符。

let mut s = String::from("hello");
s.insert(2, 'l');

16. insert_str

insert_str():在字符串的指定位置插入一个字符串。

let mut s = String::from("hello");
s.insert_str(2, "ll");

17. replace

replace():将字符串中的所有匹配项替换为另一个字符串。

let mut s = String::from("hello, world");
let new_s = s.replace("world", "Rust");

18. replace_range

replace_range():替换字符串的指定范围内的所有字符为另一个字符串。

let mut s = String::from("hello");
s.replace_range(1..3, "a");

19. split

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);

20. split_whitespace

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);

21. split_at

split_at():将字符串分成两个部分,在指定的位置进行分割。

let s = String::from("hello");
let (left, right) = s.split_at(2);

22. split_off

split_off():从字符串的指定位置分离出一个子字符串,并返回新的 String 对象。

let mut s = String::from("hello");
let new_s = s.split_off(2);

23. len

len():返回字符串的长度(以字节为单位)。

let s = String::from("hello");
assert_eq!(s.len(), 5);

24. is_empty

is_empty():检查字符串是否为空。

let s = String::from("");
assert!(s.is_empty());

25. as_bytes

as_bytes():将 String 对象转换为字节数组。

let s = String::from("hello");
let bytes = s.as_bytes();

26. into_bytes

into_bytes():将 String 对象转换为字节向量。

let s = String::from("hello");
let bytes = s.into_bytes();
assert_eq!(&[104, 101, 108, 108, 111][..], &bytes[..]);

27. clone

clone():创建一个与原始字符串相同的新字符串。

let s1 = String::from("hello");
let s2 = s1.clone();

28. eq

eq():比较两个字符串是否相等。

let s1 = String::from("hello");
let s2 = String::from("hello");
assert!(s1.eq(&s2));

29. contains

contains():检查字符串是否包含指定的子字符串。

let s = String::from("hello");
assert!(s.contains("ell"));

30. starts_with

starts_with():检查字符串是否以指定的前缀开头。

let s = String::from("hello");
assert!(s.starts_with("he"));

31. ends_with

ends_with():检查字符串是否以指定的后缀结尾。

let s = String::from("hello");
assert!(s.ends_with("lo"));

32. find

find():查找字符串中第一个匹配指定子字符串的位置。

let s = String::from("hello");
let pos = s.find("l");
assert_eq!(pos, Some(2));

33. rfind

rfind():查找字符串中最后一个匹配指定子字符串的位置。

let s = String::from("hello");
let pos = s.rfind("l");
assert_eq!(pos, Some(3));

34. trim

trim():删除字符串两端的所有空格。

let s = String::from("   hello   ");
let trimmed = s.trim();

35. trim_start

trim_start():删除字符串开头的所有空格。

let s = String::from("   hello   ");
let trimmed = s.trim_start();

36. trim_end

trim_end():删除字符串末尾的所有空格。

let s = String::from("   hello   ");
let trimmed = s.trim_end();

37. to_lowercase

to_lowercase():将字符串中的所有字符转换为小写。

let s = String::from("HeLLo");
let lower = s.to_lowercase();

38. to_uppercase

to_uppercase():将字符串中的所有字符转换为大写。

let s = String::from("HeLLo");
let upper = s.to_uppercase();

39. retain

retain():保留满足指定条件的所有字符。

let mut s = String::from("hello");
s.retain(|c| c != 'l');

40. drain

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);

41. lines

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);

42. chars

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);

43. bytes

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);

44. as_str

as_str():将 String 对象转换为字符串切片。

let s = String::from("hello");
let slice = s.as_str();

45. as_mut_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);

46. remove_matches

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/603037.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网络层:IP地址

网络层&#xff1a;IP地址 笔记来源&#xff1a; 湖科大教书匠&#xff1a;IP地址 声明&#xff1a;该学习笔记来自湖科大教书匠&#xff0c;笔记仅做学习参考 IP地址是因特网(Internet)上的主机和路由器所使用的地址&#xff0c;用于标识两部分信息&#xff1a; 网络编号&am…

Allegro16.6详细教程(一)

第一章User Interface 本章的主要內容介紹allegro操作介面,透過本章學習可以對Allegro的工作介面有了大致的瞭解,同時也能體驗出Allegro PCB Layout時的強大功能。 A.程式的啟動 除了以上Allegro主程式,我們還會常用到以下幾個常用工具: • Padstack Designer (Padstack…

《代码日记》

代码日记 Project :Space1、new_method.py new2.pynew3.pynew4.pynew5.py new5.1.pynew6.py Project :Space 都是在D001289数据集上的测试 1、new_method.py 先划分训练集和测试集 通过稀疏自编码器进行降维至20维度 自编器参数&#xff1a; # 训练自编码器模型autoencoder …

JavaEE进阶 Spring AOP(6/1)

目录 1.什么是AOP 2.Spring AOP可以干什么 3.AOP的组成成分 4.SpringAOP实现步骤 5.SpringAOP的原理 1.什么是AOP AOP是面向切面编程&#xff0c;是一种思想 Spring AOP是一种具体的技术 2.Spring AOP可以干什么 1.用户登录状态的判断 2.统一的日志记录&#xff08;比如记录…

基于深度学习的高精度牙齿健康检测识别系统(PyTorch+Pyside6+YOLOv5模型)

摘要&#xff1a;基于深度学习的高精度牙齿健康检测识别系统可用于日常生活中检测牙齿健康状况&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的牙齿目标检测识别&#xff0c;另外支持结果可视化与图片或视频检测结果的导出。本系统采用YOLOv5目标检测模型训练数…

c++代码实现一个线程池(清晰明了,一看就懂)

线程池的应用 在我认知中&#xff0c;任何网络服务器都是一个死循环。这个死循环长下面这个样子。 基本上服务器框架都是基于这个架构而不断开发拓展的。 这个死循环总共分为四个步骤&#xff0c;可以涵盖所有客户端的需求&#xff0c;然而目前绝大多数企业不会用这样的架构。…

带有 Utopia Messenger 的免费 ChatGPT 助手

全世界都喜欢 ChatGPT&#xff01;而且这个工具从未如此易于访问。没有限制、没有VPN、没有代理和佣金。现在您可以使用 Utopia Messenger 的传奇聊天的全部功能。 ChatGPT是每个线上用户的必备工具。它为我们提供任何所需的数据&#xff0c;生成内容&#xff0c;并解决多项任…

[数据集][目标检测]目标检测数据集黄瓜数据集VOC格式1309张

数据集格式&#xff1a;Pascal VOC格式(不包含分割路径的txt文件和yolo格式的txt文件&#xff0c;仅仅包含jpg图片和对应的xml) 图片数量(jpg文件个数)&#xff1a;1308 标注数量(xml文件个数)&#xff1a;1308 标注类别数&#xff1a;1 标注类别名称:["cucumber"] 每…

图论与算法(1)图论概念

1. 图论与算法 在计算机科学中&#xff0c;图论与算法是两个重要且紧密相关的领域。图论研究图的性质和特征&#xff0c;而算法设计和分析解决问题的方法和步骤。图论提供了一种形式化的方法来描述和分析各种关系和连接&#xff0c;而算法则为解决图相关的问题提供了有效的解决…

【刷题之路】单调栈秒解每日温度

一、题目描述 原题链接&#xff1a;https://leetcode.cn/problems/daily-temperatures/ 题目描述&#xff1a; 给定一个整数数组 temperatures &#xff0c;表示每天的温度&#xff0c;返回一个数组 answer &#xff0c;其中 answer[i] 是指对于第 i 天&#xff0c;下一个更高…

【JVM】什么是双亲委派机制?

一、为什么会有这种机制&#xff1f; 类加载器将.class类加载到内存中时&#xff0c;为了避免重复加载&#xff08;确保Class对象的唯一性&#xff09;以及JVM的安全性&#xff0c;需要使用某一种方式来实现只加载一次&#xff0c;加载过就不能被修改或再次加载。 二、什么是双…

docker安装 sqlserver2017 或者 2008

一、必要条件 服务器的运行内存必须大于2GB 二、拉取2017镜像 docker pull mcr.microsoft.com/mssql/server:2017-latest三、启动镜像 docker run --name sqlserver2017 --restart always -v /home/ceshi1:/var/opt/mssql -d -e ACCEPT_EULAY -e SA_PASSWORDqwer!#123 -…

C语言参悟-运算符表达式和语句

C语言参悟-运算符表达式和语句 一、概述二、运算符0. 运算符分类1. 数学运算符2. 逻辑运算符3. 二进制运算符4. 便捷运算符 三、表达式四、语句 一、概述 在我刚开始学C语言的时候&#xff0c;语句和运算符号这些对我来说还是很陌生的。 现在来看我对于这个的理解其实就是一种…

AUTOSAR架构介绍

简介 AUTOSAR&#xff08;AUTomotive Open System ARchitecture&#xff09;是一种面向汽车电子系统的软件架构标准。AUTOSAR为汽车电子系统提供一种开放式的软件架构标准&#xff0c;以促进汽车电子系统的可重用性、互操作性和可扩展性。它包括一系列的规范和标准&#xff0c…

Force Dimension 全系列触觉反馈装置

力觉或触觉是人体感官中具有双向传递信息能力的信息载体。借助于力反馈&#xff0c;人们可以真实的按照人类的肢体语言进行人机自然互动和信息交流&#xff0c;用户通过应用力反馈&#xff0c;可以获得和触摸实际物体时相同的运动感&#xff0c;从而产生更真实的沉浸感。 力反馈…

毕业遭失业,前途一片黑暗...不得已转行软件测试,太多心酸和无助...

大家好&#xff0c;我叫小涵&#xff0c;一名应届毕业生&#xff0c;目前已经成功转行互联网。写这篇文章的目的是因为很多人不喜欢自己的现状&#xff0c;想通过学习改变&#xff0c;奈何没有出路&#xff0c;所以想为这部分人提供一些思路&#xff1b;其次文章会总结我自己转…

汽车电子设计之SBC芯片

参考英飞凌SBC官网资料&#xff1a;https://www.infineon.com/cms/cn/product/automotive-system-ic/system-basis-chips-sbc/ SBC芯片在汽车电子领域可谓占一席之地了。那么什么是SBC&#xff1f;怎么用&#xff1f;用在哪里&#xff1f;主要特性&#xff1f; 目录 1.什么是…

unity Sockets通信 使用UDP协议,设置客户端电脑网络配置,使用新线程获取数据,解决卡顿问题,

今天调试和服务器连接&#xff0c;发现始终获取不到服务器的数据&#xff0c; 电脑和服务器都在同一局域网&#xff0c;仍然获取不到&#xff0c; 下面是电脑环境配置&#xff0c; 第一步&#xff1a; 设置网络为专用网络&#xff0c;然后点击配置防火墙和安全设置&#xff0c;…

Unity——2D小游戏笔记整理

【每日一句&#xff1a;清晨和夜晚都请用尽全力去生活】 目录 一、环境搭建 二、人物 三、相机跟随人物移动 四、平铺精灵 五、血条跟随敌人行走 六、脚本逻辑 【玩家行走方法】 【玩家跳跃方法】 【改变玩家血量值方法】 【创建玩家子弹方法】 【主角血量&#xff…

《计算机网络——自顶向下方法》精炼——3.7(1)

少而好学,如日出之阳;壮而好学,如日中之光;志而好学,如炳烛之光。——刘向 文章目录 拥塞控制方法ATM ABR拥塞控制 TCP拥塞控制TCP拥塞控制算法的实现慢启动拥塞避免快速恢复总结 拥塞控制方法 在上一篇文章中&#xff0c;我们介绍了在数据传输过程中出现的问题。本节将简要介…