Rust 字符串 初步了解

news2024/11/17 23:52:42

rust 的字符串 。字符串不是复合类型,

String&str

  • String 具有所有权,是存储在堆上的。
  • &str 没有所有权,是对 String 的引用。字符串字面量也是 &str 类型,存储在栈上。

切片(slice)

对于字符串而言,切片就是对字符串一部分的引用。

let s = String::from("hello");

let s1 = &s[0..5]; // 不包含终止索引 hello

创建切片的语法:[开始索引..终止索引]。(该语法是一个右半开区间) 。
切片数据结构:保存开始的位置(指针)和切片的长度。

.. range 序列 语法。

包含第一个字节或最后一个字节时,开始索引或最后索引可以省略。

let s = String::from("hello");

let s1 = &s[..2]; // he

let s2 = &s[2..]; // llo

let s3 = &s[..]; // hello

注意
在使用切片时,需要保证索引落在字符的边界上
因为切片上的索引指的是字节,而不是字符,而且字符串使用的编码是 UTF-8
所以当一个字符占用多个字节时,索引可能不在字符的边界上,导致没有取到完成的字符,出现错误。

字符串切片的类型标识为 &str
所以切片(slice)是一个不可变引用。

其他切片

数组也可以进行切片。
切片是对集合的部分引用,所以所有是集合的类型都可以进行切片。

字符串字面量也是切片,因为类型也是 &str

字符串

字符串与字符:

  • 字符: Unicode 类型,每个字符占用 4 个字节空间。
  • 字符串: UTF-8 类型,每个字符占用的字节数是变化的(1-4).

语言级别上的字符串类型只有 str 。(编程语言提供的原生字符串类型)
标准库中,还有多种不同用途的字符串类型:用的最广的是 String 类型。(额外的字符串处理工具)

strString

  • str 类型是硬编码进可执行文件,无法被修改。
  • String 是一个可增长、可改变且具有所有权的 UTF-8 编码字符串。(&str 也是UTF-8 字符串)

String 与 &str 的转换

&strString

  • String::from("hello")
  • "hello".to_string()

String&str

  • 取引用

Rust 不允许进行字符串索引,因为索引也是按照字节的,可能会落在字符上,导致无法取到完整的字符。

操作字符串

String 的常用方法:

追加(Push)

  • push() 追加 字符
  • push_str() 追加 字符串

在用来的字符串上追加,不会返回新的字符串。
字符串必须是可变的,即必须使用 mut 修饰

let s = String::from("hello");

s.push(','); // hello,

s.push_str(" rust"); // hello, rust

插入(Insert)

  • insert() 插入单个字符 char
  • insert_str() 插入字符串字面量 &str
    需要传入两个参数:
  1. 字符(串)插入位置的索引。(从0开始计数,越界会出现错误)。
  2. 要插入的字符串。

在原来的字符串上修改,字符串必须是 可变 的,必须由 mut 关键字修饰。

fn main() {
	let mut s = String:from("hello");
	
	s.insert(5,','); // hello,
	
	s.insert_str(6," I like"); // hello, I like
}

替换(Replace)

replace

适用于 String&str 类型。

需要两个参数:

  1. 要被替换的字符串。
  2. 新的字符串。
    该方法会替换掉所有的匹配到的字符串。
    该方法返回一个新的字符串,不是操作原来的字符串
fn main() {
	let s = String::from("hello rust");
	let new_s = s.replace("rust", "RUST"); // hello RUST
}
replacen

适用于 String&str 类型。

需要三个参数:

  1. 前两个参数与 replace() 方法一样。
  2. 第三个参数表示替换的个数。
    该方法放回一个新的字符串,不是操作原来的字符串
fn main() {
	let s = String::from("hello rust rust");
	let new_s = s.replacen("rust", "RUST",1); // hello RUST rust
}
replace_range

仅适用于 String 类型。

需要两个参数:

  1. 要替换字符串的范围(Range)。
  2. 新的字符串。
    直接操作原来在字符串,不会返回新的字符串。
    需要使用 mut 关键字修饰
fn main() {
	let s = String::from("hello rust rust");
	s.replace_range(0..1,"H"); // Hello rust rust
}

删除(Delete)

1. pop —— 删除并返回字符串的最后一个字符

直接操作原来的字符串。
存在返回值,返回值是一个 Option 类型,如果字符串为空,则返回 None

fn main() {
	let mut s = String::from("hello");
	let s1 = s.pop(); // hell s1:o
	let s2 = s.pop(); // hel s2:l
}
2. remove —— 删除并返回字符串中指定位置的字符

直接操作原来的字符串。
存在返回值,返回值是删除位置的字符串。

接受一个参数:

  • 表示该字符起始索引位置。

remove() 方法按照字节处理字符串,要求所给的索引落在字符的边界位置。

fn main() {
    let mut string_remove = String::from("测试remove方法");
    println!(
        "string_remove 占 {} 个字节",
        std::mem::size_of_val(string_remove.as_str())
    );
    // 删除第一个汉字
    string_remove.remove(0);
    // 下面代码会发生错误
    // string_remove.remove(1);
    // 直接删除第二个汉字
    // string_remove.remove(3);
    dbg!(string_remove);
}
3. truncate —— 删除字符串中从指定位置到结尾的全部字符

直接操作原来的字符串。
无返回值。
truncate() 方法按照字节来处理字符串,要求参数所给的位置是合法的字符边界。

fn main() {
    let mut string_truncate = String::from("测试truncate");
    string_truncate.truncate(3); // 测
    dbg!(string_truncate);
}
4. clear —— 清空字符串

直接操作原来的字符串。
调用后,删除字符串中的所有字符。

fn main() {
    let mut string_clear = String::from("string clear");
    string_clear.clear();
    dbg!(string_clear);
}

连接(Concatenate)

1. 使用 + 或者 += 连接字符串

右边的参数必须为字符串的切片引用类型(Slice)。

调用 + 时,相当于调用了 std::string 标准库中的 add() 方法,add() 方法的第二个参数是一个引用的类型。
因此,在使用 + 时,必须传递切片引用类型,不能直接传递 String 类型

返回一个新的字符串

fn main() {
    let string_append = String::from("hello ");
    let string_rust = String::from("rust");
    // &string_rust会自动解引用为&str
    let result = string_append + &string_rust;
    let mut result = result + "!"; // `result + "!"` 中的 `result` 是不可变的
    result += "!!!";

    println!("连接字符串 + -> {}", result);
}
2. 使用 format! 连接字符串

适用于 String&str
用法与 print! 的用法类型。

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

字符串转义

通过转义的方式 \ 输出 ASCII 和 Unicode 字符。

fn main() {
    // 通过 \ + 字符的十六进制表示,转义输出一个字符
    let byte_escape = "I'm writing \x52\x75\x73\x74!";
    println!("What are you doing\x3F (\\x3F means ?) {}", byte_escape);

    // \u 可以输出一个 unicode 字符
    let unicode_codepoint = "\u{211D}";
    let character_name = "\"DOUBLE-STRUCK CAPITAL R\"";

    println!(
        "Unicode character {} (U+211D) is called {}",
        unicode_codepoint, character_name
    );

    // 换行了也会保持之前的字符串格式
    // 使用\忽略换行符
    let long_string = "String literals
                        can span multiple lines.
                        The linebreak and indentation here ->\
                        <- can be escaped too!";
    println!("{}", long_string);
}

不转义的情况:

fn main() {
    println!("{}", "hello \\x52\\x75\\x73\\x74");
    let raw_str = r"Escapes don't work here: \x3F \u{211D}";
    println!("{}", raw_str);

    // 如果字符串包含双引号,可以在开头和结尾加 #
    let quotes = r#"And then I said: "There is no escape!""#;
    println!("{}", quotes);

    // 如果还是有歧义,可以继续增加,没有限制
    let longer_delimiter = r###"A string with "# in it. And even "##!"###;
    println!("{}", longer_delimiter);
}

操作 UTF-8 字符串

字符

Unicode 字符的方式遍历字符串,使用 chars 方法:

for c in "中国人".chars() {
 // c 为 字符串中的每个字符
}

字节

遍历每个字节 ,使用 bytes()

for b in "中国人".bytes() {
	// b 为 字符串的每个字节
}

获取子串

想要准确的从 UTF-8 中获取子串比较困难,标准库并没有提供对应的方法,可以使用第三方库。
推荐 库 utf8_slice

请添加图片描述
请添加图片描述

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

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

相关文章

线性代数 --- 为什么LU分解中L矩阵的行列式一定等于(+-)1?

以下是关于下三角矩阵L的行列式一定等于-1的一些说明 证明&#xff1a;在LU分解中&#xff0c;下三角矩阵L的行列式一定是. 在证明之前&#xff0c;我这里先补充几条关于行列式的性质&#xff1a; 性质1&#xff1a;对于三角矩阵而言&#xff0c;不论是上三角矩阵还是下三角矩…

Qt6学习笔记:对象树

使用QObject及其子类创建的对象是以对象树的形式来组织的。创建一个QObject对象时若设置一个父对象&#xff0c;它就会被添加到父对象的子对象列表里&#xff0c;一个父对象被删除时&#xff0c;其全部的子对象都会自动删除。QObject类的构造函数里有一个参数用于设置对象的父对…

PyTorch基础操作

一、Tensor 在 PyTorch 中&#xff0c;张量&#xff08;Tensor&#xff09;是一个核心概念&#xff0c;它是一个用于存储和操作数据的多维数组&#xff0c;类似于 NumPy 的 ndarray&#xff0c;但与此同时&#xff0c;它也支持 GPU 加速&#xff0c;这使得在大规模数据上进行科…

数据结构和算法-希尔排序(增量序列 算法实现 性能分析 稳定性)

文章目录 希尔排序过程小结增量序列不是固定的 算法实现算法性能分析稳定性小结 希尔排序 基本有序&#xff0c;就是存在有序的子序列 通过增量4得到各个子表 对各个子表分别进行插入排序 缩小增量&#xff0c;再除2&#xff0c;此时的子表 对各个子表插入排序 缩小增量&…

数据库设计——DQL

D Q L \huge{DQL} DQL ⭐⭐⭐⭐⭐ DQL&#xff1a;数据库查询语言&#xff0c;用来查询数据库中的记录&#xff0c;非常的重要&#xff0c;对于数据库的操作修改相对来讲还是较少部分&#xff0c;绝大多数操作都是数据查询。 整体的语法结构&#xff1a; 基本查询 示例&#…

2024最新Java基础面试题大全(一)

1、String可以被继承&#xff1f; 不能被继承&#xff0c;因为String类有final修饰符&#xff0c;而final修饰的类是不能被继承的。 public final class String implements java.io.Serializable, Comparable<String>, CharSequence {// 省略...  }2、常见集合类 Java…

C语言编译器(C语言编程软件)完全攻略(第十七部分:Dev C++使用教程(使用Dev C++编写C语言程序))

介绍常用C语言编译器的安装、配置和使用。 十七、Dev C使用教程&#xff08;使用Dev C编写C语言程序&#xff09; 前面我们给出了一段完整的C语言代码&#xff0c;就是在显示器上输出“C语言中文网”&#xff0c;如下所示&#xff1a; #include <stdio.h> int main() {…

Java 新手如何使用Spring MVC RestAPI的加密

目录 前言 为什么需要加密RestAPI&#xff1f; 使用Spring Boot创建RestAPI 使用HTTPS加密RestAPI 使用Spring Security增加安全性 使用JWT实现令牌身份验证 使用Postman测试加密的RestAPI 总结 前言 作者简介&#xff1a; 懒大王敲代码&#xff0c;计算机专业…

HarmonyOS应用开发之DevEco Studio安装与初次使用

1、DevEco Studio介绍 DevEco Studio是基于IntelliJ IDEA Community开源版本打造&#xff0c;面向华为终端全场景多设备的一站式集成开发环境&#xff08;IDE&#xff09;&#xff0c;为开发者提供工程模板创建、开发、编译、调试、发布等E2E的HarmonyOS应用/服务的开发工具。…

【谷歌云】注册谷歌云 创建Compute Engine

文章目录 一、Google Cloud注册1.1 账号信息1.2 付款信息验证1.3 验证成功 二、Compute Engine创建2.1 启动Compute Engine API2.2 创建实例2.3 新建虚拟机实例2.4 等待实例创建完成2.5 查看虚拟机配置信息2.6 创建防火墙规则2.7 SSH远程连接虚拟机 三、参考链接 一、Google Cl…

坐标经纬度的基本运算(2个坐标经纬度的距离、中心点坐标经纬度范围内的坐标计算)

现在的应用大都居于LBS服务&#xff0c;用户地理位置的获取&#xff08;经纬度坐标、所属行政区域&#xff09;&#xff0c;提供服务场所的地理位置也有行政区域信息和坐标信息。 用户与服务场所的联系&#xff0c;就近服务原则的设计&#xff0c;服务场所相对于用户的排序。 …

Java JDBC整合(概述,搭建,PreparedStatement和Statement,结果集处理)

一、JDBC的概述&#xff1a; JDBC&#xff1a;是一种执行sql语句的Java APL&#xff0c;可以为多种关系类型数据库提供统一访问&#xff0c;它由一组用Java语言编写的类和接口组成。有了JDBC&#xff0c;Java人员只需要编写一次程序就可以访问不同的数据库。 JDBC APL&#xf…

代码随想录算法训练营第17天 |110.平衡二叉树 257. 二叉树的所有路径 404.左叶子之和

目录 110.平衡二叉树 &#x1f4a1;解题思路 递归 &#x1f4bb;实现代码 257. 二叉树的所有路径 &#x1f4a1;解题思路 递归 &#x1f4bb;实现代码 404.左叶子之和 &#x1f4a1;解题思路 # 递归法 &#x1f4bb;实现代码 110.平衡二叉树 题目链接&#xff1a;…

Spring整合MyBatis项目代码示例

文章目录 Spring整合MyBatis项目代码示例1、创建如下结构的项目Spring_MyBatis2、在pom.xml文件中添加以下依赖并刷新maven3、在resources文件夹下添加spring等配置文件&#xff08;applicationContext.xml&#xff0c;db.properties&#xff0c;log4j.properties&#xff09;4…

基于多反应堆的高并发服务器【C/C++/Reactor】(中)主线程反应堆模型的事件添加和处理详解

>>服务器和客户端建立连接和通信流程&#xff1a; 基于多反应堆模型的服务器结构图&#xff0c;这主要是一个TcpServer&#xff0c;关于HttpServer,主要是用了Http协议&#xff0c;核心模块是TcpServer。这里边有两种线程&#xff1a;主线程和子线程。子线程是在线程池里…

LeGO-LOAM 几个特有函数的分析(2)

接上回LeGO-LOAM 几个特有函数的分析&#xff08;1&#xff09; 二、广度优先遍历 广度优先遍历&#xff08;Breadth-First Search, BFS&#xff09;是一种用于遍历或搜索树或图的算法。这种算法从树的根&#xff08;或图的某一指定节点&#xff09;开始&#xff0c;然后探索…

软件测试|教你如何使用UPDATE修改数据

简介 在SQL&#xff08;Structured Query Language&#xff09;中&#xff0c;UPDATE语句用于修改数据库表中的数据。通过UPDATE语句&#xff0c;我们可以更新表中的特定记录或多条记录&#xff0c;从而实现数据的修改和更新。本文将详细介绍SQL UPDATE语句的语法、用法以及一…

selenium 用webdriver.Chrome 访问网页闪退解决方案

1.1.1. 解决方案&#xff1a; 1.1.1.1. 移动插件到谷歌的安装目录下 1.1.1.2. 设置环境变量 1.1.1.3. 重启电脑检查成功 解决时间&#xff1a;5min

Windows系统中Wireshark抓包工具的安装使用

在使用Windows服务器时&#xff0c;如果我们发现网络流量异常或存在异常的外发数据包行为&#xff0c;我们可以利用抓包工具来捕获网络流量包&#xff0c;并对这些流量包进行特征分析&#xff0c;以查看其来源和目的地。通过这些信息&#xff0c;我们可以进一步诊断问题。 以下…

第01章_C语言入门

第01章_C语言入门 讲师&#xff1a;尚硅谷-宋红康&#xff08;江湖人称&#xff1a;康师傅&#xff09; 官网&#xff1a;http://www.atguigu.com 适合对象 考研同学&#xff0c;且考试科目中包含数据结构等&#xff08;需要使用C/C写代码&#xff09;考研同学&#xff0c;考…