Rust学习-字符串

这篇具有很好参考价值的文章主要介绍了Rust学习-字符串。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

字符串

Rust核心语言只有一种字符串类型:str,字符串 slice,通常以被借用的形式出现,&str。
它们是一些储存在别处的 UTF-8 编码字符串数据的引用。
比如字符串字面量被储存在程序的二进制输出中,即可执行程序的只读内存段中(rodata),字符串 slice 也是如此。

String 是由标准库提供,它是可增长的、可变的、有所有权的、UTF-8 编码的字符串类型。

谈到 “字符串”时,通常指的是 String 和字符串 slice &str 类型。
注意:String 和字符串 slice 是两个东西,但都是 UTF-8 编码。因为UTF-8 编码可以表示任何数据。

新建

// 空String
let mut s = String::new();

// to_string 方法,用于任何实现了 Display trait 的类型,字符串字面量也实现了它
let data = "initial contents";
let s = data.to_string();
let s = "initial contents".to_string();

// String::from 函数从字符串字面量创建
let s = String::from("initial contents");

// 第三种方式
let s: String = "also this".into();

更新

// push_str 方法来附加字符串 slice
// push_str 方法采用字符串 slice,因为并不需要获取参数的所有权
let mut s = String::from("foo");
s.push_str("bar");

let mut s1 = String::from("foo");
let s2 = "bar";
// s2的所有权被剥夺
s1.push_str(s2);
// 执行如下行报错
// println!("s2 is {}", s2);

// push 方法被定义为获取一个单独的字符作为参数
let mut s = String::from("lo");
s.push('l');

let s1 = String::from("Hello, ");
let s2 = String::from("world!");
let s3 = s1 + &s2; // s1 被移动,不能继续使用
// + 运算符使用了 add 函数
// fn add(self, s: &str) -> String
// 标准库中的 add 使用泛型定义。这里的 add 签名使用具体类型代替泛型
// add 函数的 s 参数:只能将 &str 和 String 相加,不能将两个 String 值相加
// &s2 的类型是 &String 而不是 &str。为什么还能编译呢?
// 解引用强制转换(deref coercion),&String 可以被 强转(coerced)成 &str
// 它把 &s2 变成了 &s2[..]
// add 没有获取参数的所有权,所以 s2 在这个操作后仍然是有效的 String
// self 没有 使用 &
// s1 的所有权将被移动到 add 调用中,之后就不再有效

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

替换

// cat src/main.rs
fn main() {
    let string_replace = String::from("I like rust. Learning rust is my favorite!");
    let new_string_replace = string_replace.replace("rust", "RUST");
    dbg!(new_string_replace); // 打印宏
    let s = "12345";
    let new_s = s.replace("3", "t");
    dbg!(new_s); // 打印宏
}

[src/main.rs:4] new_string_replace = "I like RUST. Learning RUST is my favorite!"
[src/main.rs:7] new_s = "12t45"

不能索引

String 是一个 Vec 的封装

let len = String::from("Здравствуйте").len(); // 24

Rust不允许索引字符串的字符的原因:
(1)索引操作预期需要常数时间 (O(1)),但对于 String,Rust 必须从开头到索引位置遍历来确定有多少有效的字符,所以不是 (O(1))
(2)一个字符串字节值的索引并不总是对应一个有效的 Unicode 标量值,为了避免返回意外的值并造成不能立刻发现的 bug,请见示例

注意:如下字符串中的首字母是西里尔字母的 Ze,而不是阿拉伯数字 3

fn main() {
    let hello = "Здравствуйте";
    println!("hello={}", hello);
    println!("the first data {}", &hello[0]);
}

// the type `str` cannot be indexed by `{integer}`
// you can use `.chars().nth()` or `.bytes().nth()`

改为如下:

fn main() {
    let hello = "Здравствуйте";
    println!("hello={}", hello);
    println!("the first char {:?}", hello.chars().nth(0));
    println!("the first byte {:?}", hello.bytes().nth(0));
}
// 当使用 UTF-8 编码时,З 的第一个字节 208,第二个是 151
// 208 自身并不是一个有效的字母
// the first char Some('З')
// the first byte Some(208)

不能像python那样使用索引去访问第n个字符

字符串 slice

使用 [] 和一个 range 来创建含特定字节的字符串 slice

let hello = "Здравствуйте";
let s = &hello[0..4]; // s是一个&str, “Зд”

// 如下panic
// &hello[0..1]

索引必须是usize类型,索引不能是负数。
如果起始索引是0,可以简写为&s[…n]
如果终止索引是String的最后一个字节,那么可以简写为&s[n…]
如果要引用整个String,那么可以简写为&s[…]

字符串切片引用的索引必须落在字符之间的边界位置
但是由于rust的字符串是UTF-8编码的,因此必须要小心

字符串的遍历

有效的 Unicode 标量值可能会由不止一个字节组成

// 操作单独的 Unicode 标量值
for c in "नमस्ते".chars() {
    println!("{}", c);
}
// 返回每一个原始字节
for b in "नमस्ते".bytes() {
    println!("{}", b);
}

比较 String、str、&str、&String、Box 或 Box<&str> 的区别

fn main() {
	// String:动态的,可增长的字符串类型
	// 它被分配在堆上并且可以修改
	// 常用于需要创建或修改字符串的场合
	let mut s1 = String::from("hello");
	s1.push_str(", world!");
	println!("s1={}", s1);
	print_type_of(&s1); // alloc::string::String

	// str:不可变的固定长度的字符串类型
	// 通常以切片 &str 的形式出现
	// 常用于固定的、不需要修改的字符串
	let s2: &str = "Hello, world!";
	println!("s2={}", s2);
	print_type_of(&s2); // &str

	// &String:指向 String 的引用,常用于函数参数,以便可以接受 String 类型也可以接受 &str 类型
	let s31 = String::from("Hello, world!");
	let t31: &String = &s31;
	let s32 = String::from("Hello, world!");
	let t32: &String = &s32;
	println!("t31={}", t31); // &alloc::string::String
	print_type_of(&t31);
	println!("t32={}", t32); // &alloc::string::String
	print_type_of(&t32);

	// Box:一个堆分配的固定长度字符串
	// 它的使用比较罕见,只有在一些特殊的场合才会用到。
	let s41: Box<str> = Box::from("Hello, world!");
	println!("s41={}", s41);
	print_type_of(&s41); // alloc::boxed::Box<str>

	// Box<&str>:一个罕见的类型,通常不会在 Rust 代码中出现。
	// 它是一个指向 str 的堆分配引用
	let s51: &str = "Hello, world!";
	let t51: Box<&str> = Box::new(s51);
	println!("t51={}", t51);
	print_type_of(&t51); // alloc::boxed::Box<str>
}

fn print_type_of<T>(_: &T) {
    println!("{}", std::any::type_name::<T>());
}

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

fn main() {
    let s = "Hello, Rust string!";
    print_type_of(&s); // &str

    let s = "Hello, Rust string!".to_string();
    print_type_of(&s); // alloc::string::String

    let s1 = &s;
    print_type_of(&s1); // &alloc::string::String

    let s2 = &s[0..5]; // 类型变换,&alloc::string::String 转 &str
    print_type_of(&s2); // &str
}

fn print_type_of<T>(_: &T) {
    println!("{}", std::any::type_name::<T>());
}

String和&str的相互转换

// &str 转为 String
let s = String::from("hello");
let s = "hello".to_string();

// String转为&str
let s = String::from("hello");
let slice = &s[..2];
println!("{slice}");   // 直接打印slice切片引用,没有解引用。这是因为deref 隐式强制转换,由编译器完成

附录

UTF-8 可以表示所有可打印的 ASCII 字符,以及不可打印的字符
UTF-8 还包括各种额外的国际字符,如中文字符和阿拉伯字符
UTF-8 表示字符时,每个代码都由一个或多个字节的序列来表示
(1)(0-127)ASCII 范围内的代码由一个字节表示
(2)(128-2047) 范围内的码位由两个字节表示
(3)(2048-65535) 范围内的代码点由三个字节表示
(4)(65536-1114111) 范围内的代码由四个字节表示文章来源地址https://www.toymoban.com/news/detail-563524.html

到了这里,关于Rust学习-字符串的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 30天拿下Rust之字符串

    概述         在Rust中,字符串是一种非常重要的数据类型,用于处理文本数据。Rust的字符串是以UTF-8编码的字节序列,主要有两种类型:str和String。其中,str是一个对字符数据的不可变引用,更像是对现有字符串数据的“视图”,而String则是一个独立、可变更的字符串实

    2024年03月12日
    浏览(36)
  • rust里如何判断字符串是否相等呢?

    在 Rust 中,有几种方法可以判断字符串是否相等。下面是其中几种常见的方法: 使用 == 运算符:可以直接使用 == 运算符比较两个字符串是否相等。例如: 这段代码会输出 “字符串不相等”,因为 str1 和 str2 不是相同的字符串。 2. 使用 eq 方法:字符串类型实现了 PartialEq

    2024年02月14日
    浏览(37)
  • 【编程】Rust语言入门第4篇 字符串

    Rust 中的字符是 Unicode 类型,因此每个字符占据 4 个字节内存空间,但字符串不一样,字符串是 UTF-8 编码,也就是字符串中的字符所占的字节数是变化的(1 - 4)。 常见的字符串有两种: str,通常是引用类型, str ,即字符串字面常量,字符串切片。 std::string::String 类型 str 的变

    2024年02月20日
    浏览(47)
  • Rust字符串:安全、高效和灵活的数据类型

    Rust是一种现代的系统级编程语言,以其出色的内存安全性和高性能而受到广泛关注。在Rust中,字符串是一种重要的数据类型,它具有独特的特点,使其在处理文本和字符数据时成为理想的选择。本文将深入探讨Rust字符串的特性,包括安全性、高效性和灵活性,以帮助您更好

    2024年01月19日
    浏览(45)
  • 算法leetcode|87. 扰乱字符串(rust重拳出击)

    使用下面描述的算法可以扰乱字符串 s 得到字符串 t : 如果字符串的长度为 1 ,算法停止 如果字符串的长度 1 ,执行下述步骤: 在一个随机下标处将字符串分割成两个非空的子字符串。即,如果已知字符串 s ,则可以将其分成两个子字符串 x 和 y ,且满足 s = x + y 。 随机

    2024年02月05日
    浏览(32)
  • Rust中的字符串处理及相关方法详解

    在Rust中,字符串是一种非常重要的数据类型,而 String 类型则提供了对动态可变字符串的支持。本文将介绍一些常见的字符串处理方法以及相关示例代码。 在Rust中,有多种方式创建字符串,以下是一些常见的例子: push_str()方法 push_str() 方法用于将一个字符串切片附加到 S

    2024年02月19日
    浏览(25)
  • 没有jodatime,rust里怎么将字符串转为日期呢?

    在 Rust 中,有多种方法可以在时间和字符串之间进行转换。以下是五种常见的方式:

    2024年02月14日
    浏览(26)
  • Rust 标准库字符串类型String及其46种常用方法

    Rust主要有两种类型的字符串:str和String str 由[u8]表示,UTF-8编码的字符串的引用,字符串字面值,也称作字符串切片。&str用于查看字符串中的数据。它的大小是固定的,即它不能调整大小。 String String 类型来自标准库,它是可修改、可变长度、可拥有所有权的同样使用UTF

    2024年02月07日
    浏览(82)
  • Rust每日一练(Leetday0029) 柱状图、最大矩形、扰乱字符串

    目录 84. 柱状图中最大的矩形 Largest-rectangle-in-histogram  🌟🌟🌟 85. 最大矩形 Maximal Rectangle  🌟🌟🌟 87. 扰乱字符串 Scramble String  🌟🌟🌟 🌟 每日一练刷题专栏 🌟 Rust每日一练 专栏 Golang每日一练 专栏 Python每日一练 专栏 C/C++每日一练 专栏 Java每日一练 专栏 给定  n

    2024年02月09日
    浏览(36)
  • 【零基础学Rust | 基础系列 | 数据结构】元组,数组,向量,字符串,结构体

    在Rust编程语言中,数据结构是组织和存储数据的一种方式,它们使得数据可以高效地被访问和操作。本章将详细介绍元组,数组,向量,字符串,和结构体这几种基本的数据结构。 元组是Rust编程语言中的一种复合数据类型,它可以包含多个值,这些值可以是不同类型。元组

    2024年02月11日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包