rust字符串

标准库提供了String结构体表示字符串。
String实际上就是Vec<u8>的封装。唯一的不同是String的方法假定Vec<u8>中的二进制都是utf8编码的

pub struct String {vec: Vec<u8>,
}

一、定义String

1.使用new方法创建空字符串

let string = String::new();

2.使用from方法创建

let hello = String::from("Hello");
let hello = String::from("你好");

3.使用to_string方法创建

let one = 1.to_string(); // 整数到字符串
let float = 1.3.to_string(); // 浮点数到字符串
let slice = "hello".to_string(); // 字符串切片到字符串

4.使用format!宏

let s = format!("{}{}{}", 1, 'a', "bc");

二、使用String

因为String实现了Deref Target=str,所以String自动实现了str的所有方法。
(一)长度
有两个长度,字节数和字符数。
因为使用的utf8编码,所以一个字符可能有多个字节,所以字节数和字符数可能不相等。
1.字节数
len函数返回的是字节数

let s = "hello";
let len = s.len();
这里len的值是5。let s = "你好";
let len = s.len();
这里len的值是6。因为中文是UTF-8编码的,每个字符3个字节,所以长度为6。

2.字符数
想要获取字符数比较麻烦。先用chars()返回一个迭代器,然后再返回这个迭代器的长度。

chars
chars返回一个迭代器,元素类型是char。
例子

let s = "hello你好";
let len = s.chars().count();
这里len的值是7,因为一共有7个字符。

(二)获取字符
String不支持[]下标访问
为什么不支持呢?因为字符编码用的是utf8,一个字符占多个字节。而使用下标只能获得一个字节,显然这一个字节是不能代表字符的。
无效的Rust代码:

let hello = "你好";
let answer = &hello[0];
“你”是三个字节,而hello[0]只是一个字节,所以这是错误的。

那么该如何获取字符?
首先要明确获取字符还是字节。
1.获取字符,也就是char
(1)使用 chars 方法
获取单字符
先使用chars返回一个迭代器,然后使用迭代器的nth方法获取第n个字符,索引从0开始。

实例

fn main() {let s = String::from("EN中文");let a = s.chars().nth(2);println!("{:?}", a);
}
运行结果:
Some('中')

遍历所有字符
实例

fn main() {let s = String::from("hello中文");for c in s.chars() {println!("{}", c);}
}

(2)使用char_indices
返回一个迭代器,元素是(i, c),i是索引,c是字符。
例子

let word = "goodbye";
let count = word.char_indices().count();
assert_eq!(7, count);
let mut char_indices = word.char_indices();
assert_eq!(Some((0, 'g')), char_indices.next());
assert_eq!(Some((1, 'o')), char_indices.next());
assert_eq!(Some((2, 'o')), char_indices.next());
assert_eq!(Some((3, 'd')), char_indices.next());
assert_eq!(Some((4, 'b')), char_indices.next());
assert_eq!(Some((5, 'y')), char_indices.next());
assert_eq!(Some((6, 'e')), char_indices.next());
assert_eq!(None, char_indices.next());
for (i, c) in word.char_indices(){println!("{}", c);
}

2.获取字节,也就是u8
(1)使用 bytes 方法。
bytes
返回迭代器,元素是u8
例子

let s = String::from("你好");
let mut bytes = s.bytes();
for b in bytes {println!("{b}");
}
打印
228
189
160
229
165
189

(2)使用as_bytes
as_bytes
将String转换成&[u8]。
与此方法的相反的是from_utf8。
例子

let s = String::from("你好");
for i in s.as_bytes() {println!("{}", i);
}

(三)截取子串
1.通过字节位置截取
可以使用 [] 和一个range来创建含特定字节的字符串切片
实例

fn main() {let s = String::from("EN中文");let sub = &s[0..2];println!("{}", sub);
}
运行结果:
EN

使用这种方法截取时,必须保证字节位置是char的边界,否则会崩溃
实例

fn main() {let s = String::from("EN中文");let sub = &s[0..3];     //会崩溃println!("{}", sub);
}

2.通过字符位置截取

fn substr(s: &str, start: usize, length: usize) -> String {s.chars().skip(start).take(length).collect()
}
fn main() {let s1 = "中国-China";println!("{:?}", substr(s1, 1, 100));println!("{:?}", substr(s1, 0, 2));let s2 = String::from("中国-China");println!("{:?}", substr(&s2, 1, 100));println!("{:?}", substr(&s2, 0, 2));
}

(四)拼接
1.使用push追加char

let mut s = String::from("run");
s.push('!'); // 追加字符

2.使用push_str追加&str

let mut s = String::from("run");
s.push_str("oob"); // 追加字符串切片

3.用 + 号拼接String

let s1 = String::from("Hello, ");
let s2 = String::from("world!");
let s3 = s1 + &s2; // 注意s1被移动了,不能继续使用

这个语法也可以拼接&str:

let s1 = String::from("tic");
let s2 = String::from("tac");
let s3 = String::from("toe");
let s = s1 + "-" + &s2 + "-" + &s3;

4.使用format!宏

let s1 = String::from("tic");
let s2 = String::from("tac");
let s3 = String::from("toe");
let s = format!("{}-{}-{}", s1, s2, s3);

(五)插入
insert
在指定字节位置插入一个字符。
Panics
如果idx大于String的长度,或者它不在char边界上,就会出现panics。
例子

let mut s = String::with_capacity(3);
s.insert(0, 'f');
s.insert(1, 'o');
s.insert(2, 'o');
assert_eq!("foo", s);

insert_str
在指定字节位置处插入&str。
Panics
如果idx大于String的长度,或者它不在char边界上,就会出现panics。
例子

let mut s = String::from("bar");
s.insert_str(0, "foo");
assert_eq!("foobar", s);

(六)删除
truncate
将此String缩短为指定的字节长度。
如果new_len大于字符串的当前长度,则无效。
Panics
如果new_len不位于char边界上,就会出现panics。
例子

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

pop
删除最后一个字符并返回它。
如果String为空,则返回None。
例子

let mut s = String::from("foo");
assert_eq!(s.pop(), Some('o'));
assert_eq!(s.pop(), Some('o'));
assert_eq!(s.pop(), Some('f'));
assert_eq!(s.pop(), None);

remove
从指定字节位置删除char并将其返回。
Panics
如果idx大于或等于String的长度,或者它不位于char边界上,就会出现panics。
例子

let mut s = String::from("foo");
assert_eq!(s.remove(0), 'f');
assert_eq!(s.remove(1), 'o');
assert_eq!(s.remove(0), 'o');

retain
仅保留特定的字符。
换句话说,使f© 返回false,来删除所有字符c。
例子

let mut s = String::from("f_o_ob_ar");
s.retain(|c| c != '_');
assert_eq!(s, "foobar");
使用外部状态来确定要保留哪些元素。
let mut s = String::from("abcde");
let keep = [false, true, true, false, true];
let mut iter = keep.iter();
s.retain(|_| *iter.next().unwrap());
assert_eq!(s, "bce");

clear
删除所有内容。
虽然这意味着String的长度为零,但它并未触及其容量。
例子

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

drain
批量删除指定范围,并以迭代器的形式返回所有删除的字符。
返回的迭代器在字符串上保留一个可变借用以优化其实现。
Panics
如果起始点或结束点不在char边界上,或超出边界,就会出现panic。
Leaking
如果返回的迭代器离开作用域而没有被丢弃 (例如,由于core::mem::forget),则字符串可能仍包含任何耗尽字符的副本,或者可能任意丢失字符,包括范围外的字符。
例子

let mut s = String::from("αis alpha, βis beta");
let beta_offset = s.find('β').unwrap_or(s.len());
// 删除范围直到字符串中的 β
let t: String = s.drain(..beta_offset).collect();
assert_eq!(t, "αis alpha, ");
assert_eq!(s, "βis beta");
// 全范围清除字符串,就像 `clear()` 一样
s.drain(..);
assert_eq!(s, "");

trim
返回除去前导和尾随空格的字符串切片。
‘Whitespace’ 是根据Unicode派生的核心属性White_Space的术语定义的,该属性包括换行符。
例子

let s = "\n Hello\tworld\t\n";
assert_eq!("Hello\tworld", s.trim());

trim_start
返回除去前导空格的字符串切片。
‘Whitespace’ 是根据Unicode派生的核心属性White_Space的术语定义的,该属性包括换行符。
文字方向性
字符串是字节序列。start在此上下文中表示该字节字符串的第一个位置; 对于从左到右的语言 (例如英语或俄语),这将是左侧; 对于从右到左的语言 (例如阿拉伯语或希伯来语),这将是右侧。
例子

let s = "\n Hello\tworld\t\n";
assert_eq!("Hello\tworld\t\n", s.trim_start());
Directionality:
let s = " English ";
assert!(Some('E') == s.trim_start().chars().next());
let s = " עברית ";
assert!(Some('ע') == s.trim_start().chars().next());

trim_end
返回除去尾随空格的字符串切片。
‘Whitespace’ 是根据Unicode派生的核心属性White_Space的术语定义的,该属性包括换行符。
文字方向性
字符串是字节序列。end在此上下文中表示该字节字符串的最后位置; 对于从左到右的语言 (例如英语或俄语),这将在右侧; 对于从右到左的语言 (例如阿拉伯语或希伯来语),将在左侧。
例子

let s = "\n Hello\tworld\t\n";
assert_eq!("\n Hello\tworld", s.trim_end());
Directionality:
let s = " English ";
assert!(Some('h') == s.trim_end().chars().rev().next());
let s = " עברית ";
assert!(Some('ת') == s.trim_end().chars().rev().next());

(七)转换
as_str
将String转换为&str。
例子

let s = String::from("foo");
assert_eq!("foo", s.as_str());

as_mut_str
将String转换为&mut str。
例子

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

parse
将此字符串切片解析为另一种类型。
由于parse非常通用,因此可能导致类型推断问题。需要指定类型或使用turbofish语法
parse可以解析为任何实现FromStr trait的类型。
Errors
如果无法将此字符串切片解析为所需的类型,则将返回Err。
例子

let four: u32 = "4".parse().unwrap();
assert_eq!(4, four);
使用turbofish
let four = "4".parse::<u32>();
assert_eq!(Ok(4), four);
无法解析:
let nope = "j".parse::<u32>();
assert!(nope.is_err());

(八)替换
replace_range
删除字符串中的指定字节范围,并将其替换为给定的字符串。
Panics
如果起始点或结束点不在char边界上,或超出边界,就会出现panic。
例子

let mut s = String::from("αis alpha, βis beta");
let beta_offset = s.find('β').unwrap_or(s.len());
// 替换范围直到字符串中的 β
s.replace_range(..beta_offset, "Αis capital alpha; ");
assert_eq!(s, "Αis capital alpha; βis beta");

replace
用另一个字符串替换模式的所有匹配项。
例子

let s = "this is old";
assert_eq!("this is new", s.replace("old", "new"));
assert_eq!("than an old", s.replace("is", "an"));
当模式不匹配时,它将此字符串切片作为String返回:
let s = "this is old";
assert_eq!(s, s.replace("cookie monster", "little lamb"));

replacen
用另一个字符串替换模式的前N个匹配项
例子

let s = "foo foo 123 foo";
assert_eq!("new new 123 foo", s.replacen("foo", "new", 2));
assert_eq!("faa fao 123 foo", s.replacen('o', "a", 3));
assert_eq!("foo foo new23 foo", s.replacen(char::is_numeric, "new", 1));
当模式不匹配时,它将此字符串切片作为String返回:
let s = "this is old";
assert_eq!(s, s.replacen("cookie monster", "little lamb", 10));

(九)分割
split_off
在给定的字节索引处将字符串拆分为两个。
返回新分配的String。self包含字节 [0, at),返回的String包含字节 [at, len)。at必须位于UTF-8代码点的边界上。
请注意,self的容量不会改变。
Panics
如果at不在UTF-8代码点边界上,或者它超出字符串的最后一个代码点,就会出现panics。
例子

let mut hello = String::from("Hello, World!");
let world = hello.split_off(7);
assert_eq!(hello, "Hello, ");
assert_eq!(world, "World!");

split_whitespace
用空格分割字符串切片。
返回的迭代器将返回作为原始字符串切片的子切片的字符串切片,并以任意数量的空格分隔。
‘Whitespace’ 是根据Unicode派生核心属性White_Space的条款定义的。 如果只想在ASCII空格上分割,请使用split_ascii_whitespace。
例子

let mut iter = "A few words".split_whitespace();
assert_eq!(Some("A"), iter.next());
assert_eq!(Some("few"), iter.next());
assert_eq!(Some("words"), iter.next());
assert_eq!(None, iter.next());
考虑所有类型的空白:
let mut iter = " Mary had\ta\u{2009}little \n\t lamb".split_whitespace();
assert_eq!(Some("Mary"), iter.next());
assert_eq!(Some("had"), iter.next());
assert_eq!(Some("a"), iter.next());
assert_eq!(Some("little"), iter.next());
assert_eq!(Some("lamb"), iter.next());
assert_eq!(None, iter.next());
如果字符串为空或全为空白,则迭代器不产生字符串切片:
assert_eq!("".split_whitespace().next(), None);
assert_eq!(" ".split_whitespace().next(), None);

split_ascii_whitespace
用ASCII空格分割字符串切片。
返回的迭代器将返回作为原始字符串切片的子切片的字符串切片,并以任意数量的ASCII空格分隔。
要改为按Unicode Whitespace进行拆分,请使用split_whitespace。
例子

let mut iter = "A few words".split_ascii_whitespace();
assert_eq!(Some("A"), iter.next());
assert_eq!(Some("few"), iter.next());
assert_eq!(Some("words"), iter.next());
assert_eq!(None, iter.next());
考虑所有类型的ASCII空白:
let mut iter = " Mary had\ta little \n\t lamb".split_ascii_whitespace();
assert_eq!(Some("Mary"), iter.next());
assert_eq!(Some("had"), iter.next());
assert_eq!(Some("a"), iter.next());
assert_eq!(Some("little"), iter.next());
assert_eq!(Some("lamb"), iter.next());
assert_eq!(None, iter.next());
如果字符串为空或全部为ASCII空格,则迭代器不产生字符串切片:
assert_eq!("".split_ascii_whitespace().next(), None);
assert_eq!(" ".split_ascii_whitespace().next(), None);

(十)contains
如果包含模式,则返回true。否则返回false。
模式 可以是 &str,char,&[char],也可以是确定字符是否匹配的函数或闭包。
例子

let bananas = "bananas";
assert!(bananas.contains("nana"));
assert!(!bananas.contains("apples"));

starts_with
如果以模式开头,则返回true。否则返回false。
模式 可以是 &str,char,&[char],也可以是确定字符是否匹配的函数或闭包。
例子

let bananas = "bananas";
assert!(bananas.starts_with("bana"));
assert!(!bananas.starts_with("nana"));

ends_with
如果模式结尾,则返回true。否则返回false。
模式 可以是 &str,char,&[char],也可以是确定字符是否匹配的函数或闭包。
例子

let bananas = "bananas";
assert!(bananas.ends_with("anas"));
assert!(!bananas.ends_with("nana"));

(十一)其他
is_empty
如果此String的长度为零,则返回true,否则返回false。

let mut v = String::new();
assert!(v.is_empty());
v.push('a');
assert!(!v.is_empty());

lines
返回一个迭代器,迭代器元素是&str。
行以\n或\r\n结尾。最后一行的结尾是可选的。
迭代器返回的行中会去掉\n或\r\n。
例子

let text = "foo\r\nbar\n\nbaz\n";
let mut lines = text.lines();
assert_eq!(Some("foo"), lines.next());
assert_eq!(Some("bar"), lines.next());
assert_eq!(Some(""), lines.next());
assert_eq!(Some("baz"), lines.next());
assert_eq!(None, lines.next());let text = "foo\nbar\n\r\nbaz";
let mut lines = text.lines();
assert_eq!(Some("foo"), lines.next());
assert_eq!(Some("bar"), lines.next());
assert_eq!(Some(""), lines.next());
assert_eq!(Some("baz"), lines.next());
assert_eq!(None, lines.next());

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

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

相关文章

【DRAM存储器六】DRAM存储器的架构演进-part3

&#x1f449;个人主页&#xff1a;highman110 &#x1f449;作者简介&#xff1a;一名硬件工程师&#xff0c;持续学习&#xff0c;不断记录&#xff0c;保持思考&#xff0c;输出干货内容 参考书籍&#xff1a;《Memory Systems - Cache, DRAM, Disk》 目录 以降低延时…

【C语言精髓 之 指针】指针*、取地址、解引用*、引用

/*** file * author jUicE_g2R(qq:3406291309)————彬(bin-必应)* 一个某双流一大学通信与信息专业大二在读 * copyright 2023.9* COPYRIGHT 原创技术笔记&#xff1a;转载需获得博主本人同意&#xff0c;且需标明转载源* language …

【C】指针初阶

指针 为了后续一些安排打基础&#xff0c;决定使用C/C作为算法主语言&#xff0c;所以从这篇文章开始&#xff0c;从指针开始总结 指针 -> 指针进阶 -> 字符串函数 -> 自定义类型 -> 动态内存管理 -> 数据结构 还有C一些基础语法的回顾&#xff08;基于算法…

【postgresql 】 ERROR: “name“ is not supported as an alias

org.postgresql.util.PSQLException: ERROR: "name" is not supported as an alias 错误&#xff1a;不支持将“name”作为别名 SELECT real_name name FROM doc_user 加上 在关键词上加上 “” 示例&#xff1a; SELECT real_name "name" FROM do…

SWIFT中最常见的内存泄漏陷阱

SWIFT中最常见的内存泄漏陷阱 如果您有内存循环&#xff0c;它将在调试器中向您显示警告&#xff1a; 如果确实有一个&#xff08;或通常是一堆&#xff09;&#xff0c;则表示您有一个泄漏的物体。 您如何预防呢&#xff1f; 就像在关闭的第一行中添加[unowned self]一样简…

“Vue进阶:深入理解插值、指令、过滤器、计算属性和监听器“

目录 引言&#xff1a;Vue的插值Vue的指令Vue的过滤器Vue的计算属性和监听器vue购物车案例总结&#xff1a; 引言&#xff1a; Vue.js是一款流行的JavaScript框架&#xff0c;它提供了许多强大的功能来简化前端开发。在本篇博客中&#xff0c;我们将深入探讨Vue的一些高级特性…

Java项目:SSM的网上书城系统

作者主页&#xff1a;Java毕设网 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 一、相关文档 1、关于雅博书城在线系统的基本要求 &#xff08;1&#xff09;功能要求&#xff1a;可以管理个人中心、用户管理、图书分类管理、图书信息管理、…

Java 函数式编程思考 —— 授人以渔

引言 最近在使用函数式编程时&#xff0c;突然有了一点心得体会&#xff0c;简单说&#xff0c;用好了函数式编程&#xff0c;可以极大的实现方法调用的解耦&#xff0c;业务逻辑高度内聚&#xff0c;同时减少不必要的分支语句&#xff08;if-else&#xff09;。 一、函数式编…

【Vue3+Vite+Ts+element-plus】vue 使用 tsx语法详解

系列文章目录 【Vue3ViteTselement-plus】 超级详细 最新 vite4vue3tselement-pluseslint-prettier 项目搭建流程 【Vue3ViteTselement-plus】使用tsx实现左侧栏菜单无限层级封装 【Ts 系列】 TypeScript 从入门到进阶之基础篇(一) ts类型篇 文章目录 系列文章目录前言一、必要…

MySQL 数据库学习(六)备份与binlog日志

1 案例1&#xff1a;完全备份与恢复 1.1 问题 练习物理备份与恢复练习mysqldump备份与恢复 1.2 方案 在数据库服务器192.168.88.50 练习数据的备份与恢复 1.3 步骤 实现此案例需要按照如下步骤进行。 步骤一&#xff1a;练习物理备份与恢复 冷备份&#xff0c;需停止数…

Python手写人脸识别

Python手写人脸识别 引言 人脸识别是一种通过计算机视觉和模式识别技术来识别和验证人脸的技术。Python是一种广泛使用的编程语言,它提供了许多强大的库和工具来实现人脸识别。 在Python中,可以使用多种方法来实现人脸识别,包括基于特征提取的方法、基于深度学习的方法等…

clickhouse学习之路----clickhouse的特点及安装

clickhouse学习笔记 反正都有学不完的技术&#xff0c;不如就学一学clickhouse吧 文章目录 clickhouse学习笔记clickhouse的特点1.列式存储2. DBMS 的功能3.多样化引擎4.高吞吐写入能力5.数据分区与线程级并行 clickhouse安装1.关闭防火墙2.CentOS 取消打开文件数限制3.安装依…

java字符串的学习总结

/* 总结: 1. ★★★★★★★String 是字符串,内容不可改变★★★★★★★★ 常用方法: (1)length() 长度(2)equals(string类型) 比较当前字符串于括号里的字符串是否相同(3)startsWith(st…

支持向量机基本原理,Libsvm工具箱详细介绍,基于支持向量机SVM的遥感图像分类

目录 支持向量机SVM的详细原理 SVM的定义 SVM理论 Libsvm工具箱详解 简介 参数说明 易错及常见问题 完整代码和数据下载链接: 基于SVM的遥感图像分类识别,基于支持向量机SVM的遥感图像分类识别(代码完整,数据齐全)_图像匹配中SVM多分类问题资源-CSDN文库 https://downloa…

Python 运行代码

一、Python运行代码 可以使用三种方式运行Python&#xff0c;如下&#xff1a; 1、交互式 通过命令行窗口进入 Python 并开始在交互式解释器中开始编写 Python 代码 2、命令行脚本 可以把代码放到文件中&#xff0c;通过python 文件名.py命令执行代码&#xff0c;如下&#xff…

ARMv7处理器

本文档介绍常见的 ARM 架构,包括 Cortex-A5,Cortex-A7, Cortex-A8, Cortex-A9, Cortex-A15. 常见的术语 DFT(Design for Test), 为了增强芯片可测性而采用的一种设计方法 APB(Advanced Peripheral Bus), 是一种低速外设总线接口,通常用于将外部设备(如I/O端口、定时器、UA…

机器学习——pca降维/交叉验证/网格交叉验证

1、pca降维&#xff1a;目的是提升模型训练速度 定义&#xff1a; 使用方法&#xff1a;给训练数据或者测试数据进行降维处理 给训练数据降维 给测试数据降维&#xff1a;这里1就要用transform&#xff0c;而不是fit_transform&#xff0c;因为之前训练数据降维时特征已经确定…

构建基于neo4j知识图谱、elasticsearch全文检索的数字知识库

前言&#xff1a; 在数字化时代&#xff0c;知识库的建设正逐渐成为企业、学术机构和个人的重要资产。本文将介绍如何使用neo4j和elasticsearch这两种强大的数据库技术来构建知识库&#xff0c;并对其进行比较和探讨。 技术栈&#xff1a; springbootvueneo4jelasticsearch…

【每日一题】1993. 树上的操作

文章目录 Tag题目来源题目解读解题思路方法一&#xff1a;深度优先搜索 写在最后 Tag 【深度优先搜索】【树】【设计数据结构】【2023-09-23】 题目来源 1993. 树上的操作 题目解读 本题是一个设计类的题目&#xff0c;对于设计类的题目就一步步的实现题目要求的成员方法即可…

【ACDC数据集】:预处理ACDC心脏3D MRI影像数据集到VOC数据集格式,nii转为jpg,label转为png

【Segment Anything Model】做分割的专栏链接&#xff0c;欢迎来学习。 【博主微信】cvxiaoyixiao 本专栏为公开数据集的预处理&#xff0c;持续更新中。 文章目录 1️⃣ ACDC数据集介绍2️⃣ ACDC数据集样例 3️⃣ 预处理ACDC目标 4️⃣ 处理结果样图 5️⃣ 代码 6️⃣ 划分测…