04|字符串:对号入座,字符串其实没那么可怕!
可怕的字符串?
- 深入了解
- 翻译
- 解释
- 总结
Rust中的字符串处理是开发中常见的任务。本文通过介绍不同类型的字符串及其特点,帮助读者更好地理解Rust中的字符串处理。文章详细介绍了`String`、`&String`、`str`、`&str`等不同类型的字符串表示及其内存结构,以及与字符串相关的`[u8]`、`&[u8]`、`&[u8; N]`、`Vec<u8>`等类型的比较。此外,还介绍了切片的概念和使用方法,以及`as_str()`、`as_bytes()`、`as_slice()`等方法的使用。文章还介绍了隐式引用类型转换、字节串转换成字符串、字符串切割成字符数组、其他字符串相关类型以及Parse方法。通过本文的阅读,读者可以快速了解Rust中字符串的各种类型及其使用方法,为日后的Rust开发提供了重要参考。文章内容丰富,涵盖了Rust中字符串处理的方方面面,对于想要深入了解Rust字符串处理的读者来说,是一篇不可多得的技术指南。
《Rust 语言从入门到实战》,新⼈⾸单¥59
全部留言(22)
- 最新
- 精选
- 一个人旅行1.String类型为struct类型,实现了Deref特征。 2.当String类型调用chars方法是,编译器会检查String类型是否实现了chars方法,检查项包括self,&self,&mut self 3.如果都没有实现chars方法,编译器则调用deref方法解引用(智能指针),得到str,此时编译器才会调用chars方法,也就是可以调用str实现的所有方法
作者回复: 👍
2023-10-27归属地:北京28 - eriklee什么时候用to_owned(),什么时候用to_string()呢?
作者回复: to_owned() 是更通用的,目的就是在只能拿到引用的情况下获得所有权(通过克隆一份资源)。to_string() 就只是转成字符串而已,这两个用法重叠,但是不完全相同。
2023-10-31归属地:北京27 - plh[思考题]: 实际上 str 上的所有方法,String 都能调用. 这个地方 对初学者需要 循序渐进地理解: 1. 最开始接触 引用的概念是 rust book 中文版 中有句话, “而更有经验的 Rustacean 会编写出示例 4-9 中的签名”, 使用的函数 签名 从 &String 转换成 &str, 见链接 https://kaisery.github.io/trpl-zh-cn/ch04-03-slices.html#%E5%AD%97%E7%AC%A6%E4%B8%B2-slice-%E4%BD%9C%E4%B8%BA%E5%8F%82%E6%95%B0, 当时觉得很神奇, 更有经验的 Rustacean, 不就是 自己的当前目标吗. 2. 随着 继续深入下去, 自然接触到了 Deref 运算符, 也就是这个地方 这个地方实现上会调用 s.defer() , 这个地方 就是一个本质. 3. Rust 既然很受广大程序员的欢迎还是有原因的, 有很多符合 "人体工程学"的特性, 其中就有 automatic referencing and dereferencing, [运算符到哪去了], 见链接 https://kaisery.github.io/trpl-zh-cn/ch05-03-method-syntax.html#--%E8%BF%90%E7%AE%97%E7%AC%A6%E5%88%B0%E5%93%AA%E5%8E%BB%E4%BA%86 4. 本课的 [隐式引用类型转换], 个人觉得 有点 歧义,可能会引起后续的麻烦. 首先 Rust 不允许自动类型隐式转换,从这个角度来说, Rust 就属于强类型语言(什么是 强类型语言这个是争议的,可以暂时不管).其次, 如果换成 automatic referencing and dereferencing(自动 引用 和解引用) ,这个说法 就更严谨一点. 个人愚见,欢迎老师同学指正.
作者回复: 很棒的思考。第3点,从初学者理解的角度来看,这个类型的转换确实是 “自动” “隐式”完成的,只不过这个隐式不是语言内置的,而是在标准库中通过Deref trait完成的。这样处理的原因在于,引入自动引用和解引用,会给初学者带来新的理解负担。官方book在这个问题上处理得并不好。另外,rust中并没有禁用 隐式 这个词。
2023-11-01归属地:四川4 - 二夕在 Rust 中,String 是一个可变的字符串类型,是用结构体定义的,而且实现了 Deref trait。str 是一个不可变的字符串切片类型。当调用一个 str 上的方法时,实际上就是通过 Deref 的自动转换机制(解引用),将 String 转换为对应的 str 切片,从而可以调用 str 上的方法。
作者回复: 非常清晰!👍
2023-11-01归属地:浙江2 - superggn简单理解: 有个东西叫 deref coercion 在类型A上调函数的时候如果 typeA 有对应方法, 直接调; 如果没有对应方法, 就往下着 typeA 有没有实现 deref 如果没实现, GG 如果 typeA 能 deref 到 typeRoot, 那么在 typeRoot 里寻找有没有对应方法 如果 typeRoot 里没有方法, 继续看 typeRoot 里有没有对应方法, 递归往下走
作者回复: 👍真棒
2023-12-13归属地:北京1 - Citroen同过学习我理解的是下面这样,有不对请老师指正,谢谢。 Rust中char是用于存放unicode单个字符的类型(最多四个字节)。 String类型只能放在堆上,通过引用所有权的形式和变量绑定,它的存储方式不是简单的char数组,而是utf8编码的字节序列,所以单独取这个序列的某一段切片,不一定能解析出具体的字符(程序里的String[a..b],这里的a和b已经是经过特殊处理的保证截取的有效性),如果能取得有效的序列片段那就是str类型,但是程序里凡是用到绑定str类型变量的地方,则必须都是引用形式存在的(&str),因为str是引用的原始片段的那段真是数据,而&str类型是一个FatPointer,它包括引用目标的起始地址和长度,所以str和&str是完全两个不同的概念。 u8就是一个存储0到255大小的类型,因为一个字节就是8位,所以[u8, N]可以看做是程序的任何类型数据的二进制表示形式。 不管是[T], Vec<T>,甚至Vec<Vec<Vec<String>>>只要Vec实现了Deref特性都并且Vec上没有的,都会层层解到最后需要的类型的方法上。
作者回复: 非常棒的思考! 0. “Rust中char是用于存放unicode单个字符的类型(最多四个字节)。”。Rust语言里面的char就是占用4个字节,固定的。 1. “程序里的String[a..b],这里的a和b已经是经过特殊处理的保证截取的有效性”。对的。 fn main() { let s = "abcdefghijk".to_string(); let a = &s[..5]; let s = "我爱中国".to_string(); let a = &s[..5]; } Running `target/debug/playground` thread 'main' panicked at src/main.rs:7:15: byte index 5 is not a char boundary; it is inside '爱' (bytes 3..6) of `我爱中国` 2. “所以str和&str是完全两个不同的概念”。对的。 3. "所以[u8; N]可以看做是程序的任何类型数据的二进制表示形式。" 。对的。 4. “不管是[T], Vec<T>,甚至Vec<Vec<Vec<String>>>只要Vec实现了Deref特性都并且Vec上没有的,都会层层解到最后需要的类型的方法上。”。对的,适用于任何类型。
2023-11-15归属地:辽宁21 - -Hedon🍭思考题:在 Rust 中,trait 是一种定义共享行为的机制。当一个类型实现了某个 trait,它就可以使用该 trait 中定义的方法。String 类型实现了 str 类型的 trait,因此可以调用 str 类型上定义的方法。
作者回复: 这句话不对:“String 类型实现了 str 类型的 trait”。String 通过实现Deref trait,目标为 str,因此可以调用 str 类型上定义的方法。
2023-10-30归属地:湖北1 - Lucas Lin对「String、&String、str、&str、&'static str 之间的关系图」有个疑问。&'static str 和 &str 都是切片引用,那 &'static str 是不是也应该和 &str 一样有个引用范围的图示?范围是整个字符串("I am a superman.")。
作者回复: 这个建议非常棒,我画下面部分的时候,没有想到这一点。这样更严谨,感谢指正。
2023-10-29归属地:中国台湾1 - 舒灿感谢评论区各位大哥的回复,不然看了这篇真要从入门到放弃了
作者回复: 哪点要放弃?你如果放弃了说明我的讲法还需要改进!
2024-01-17归属地:四川3 - 飞了的鸭子被煮了let s = String::from("value"); let s2 = s[..]; 这里如果这样声明,会报错,说str没有实现size,如果加了&就没问题,是不是说明 & 把 String的所有权借用过来后,对于 str 来说就能获取到 size,从而不报错了呢
作者回复: 定义变量是在栈上的handle,必须是固定尺寸的,因此要加个&符号取引用
2024-01-16归属地:美国