Rust常用数据结构教程 String与str,元组和数组
文章目录
- 一、String与&str
- 1.Rust中的字符串
- 2.String与&str的区别
- 3.Vec源码
- 4. str与&str
- 5.&str与String的区别总结
- 6.什么时候用String、什么时候用&str
- 7.Example
- 二、元组与数组
- 参考
一、String与&str
Rust中String的源码
#[derive(PartialEq, PartialOrd, Eq, Ord)]
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), lang = "String")]
pub struct String {
vec: Vec<u8>,
}
我们可以看到String是一个结构体
· Vec<u8>
·Vec可变数组,具体内容会在第三章
·u8是无符号整数类型,可以表示0-255之间的数
如何从01到字符串
·0101100110011010 10101001 10101011 10110110=>“原子之音"
需要解决两个问题
·需要知道何时结束
- 一种是存储结束符
- 一种是在开始存储len
如何编码,最常用的编码方式
- ASCII一个字节对应一个字符(可以表示0-255个字符)
- UTF-8一个到四个字节对应(可以辨识所有语言的字符,除了私人语言,而且可以兼容ASCII)
注:一个字节8位,大家知道为啥String内置u8的可变数组(Vec)
1.Rust中的字符串
·选择在开始长度存储
·所有的string都是utf-8
·字符串默认不可变
2.String与&str的区别
·String是结构体而&str是切片的引用
·从实体上讲String类型与str类型,因为&str没有所有权
String
- string_item
- pointer:0x213342312c011 —>指向heap中的头一个字符的地址,如"hello""h’,‘e’, “I’… 中的h
- length:3 具体个数
- Capacity:10 扩容一般翻倍
3.Vec源码
pub struct Vec<T, #[unstable(feature = "allocator_api'", issue = "32838")] A:Alocator=Global>
{
buf: RawVec<T, A>,
len: usize, //长度
}pub(crate) struct RawVec<T, A: Allocator = Global> {
ptr: Unique<T>, // 指向
cap: usize, // capacity
alloc: A,
}
4. str与&str
·一个不应存在的数据类型:切片(Rust看来)
·str就是字符串切片,就是数组切片[u8],就是动态大小的utf8字节
·str在Rust是无法直接使用的,我们经常使用&str
- Box<str>
- Rc<str>
- Arc<str>
Example:
fn main() {let mut s = String::from("hello");// 切片引用就是不可变引用,不可变引用和可变引用是互斥的let word = first_word(&s);s.clear();println!("The first word is: {}", word);
}fn first_word(s: &str) -> &str {let all_bytes = s.as_bytes();for (i, &byte) in all_bytes.iter().enumerate() {if byte == b' ' {return &s[0..i];}}&s[..]
}
编译及测试:
cargo runCompiling project v0.1.0 (/home/wangji/installer/rust/project/ch1_variables)
error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immutable--> src/main.rs:6:5|
4 | let word = first_word(&s);| -- immutable borrow occurs here
5 |
6 | s.clear();| ^^^^^^^^^ mutable borrow occurs here
7 |
8 | println!("The first word is: {}", word);| ---- immutable borrow later used hereFor more information about this error, try `rustc --explain E0502`.
error: could not compile `project` (bin "project") due to 1 previous error
5.&str与String的区别总结
·String具有所有权,而&str只是切片引用
·String的数据必须存储在heap上,而&str要看引用所代指可以在stack和data section上,也可以在heap上
6.什么时候用String、什么时候用&str
. String
- 创建需要所有权的字符,有修改需求的
&str
- 查找,只读
7.Example
String与&str的区别,与相互转换
如何通过&[u8]转换为String
&str与生命周期
fn rust_say() -> &'static str {r#"Rust said "str" is danger"#
}// &[u8] u8数组的切片引用
// 调用第三库 &[u8] -> String
fn u8_to_string(string_data: &[u8]) -> String {// String::from_utf8_lossy(string_data).to_string()// 在迭代器中使用 &s,意味着对 &u8 引用进行解引用,获取 u8 的值,// string_data.iter().map(|&s| s as char).collect()string_data.iter().map(|&s| s as char).collect()
}fn main() {// string &str// 创建容量为0的空字符串let mut item = String::new();println!("String {}: cap {}", item, item.capacity());item.push('c');println!("String {}: cap {}", item, item.capacity());// 创建容量为10的空字符串let item = String::with_capacity(10);println!("String {}: cap {}", item, item.capacity());// &str-> Stringlet item = String::from("hello world");println!("String {}: cap {}", item, item.capacity());let item = "hello world".to_string();println!("String {}: cap {}", item, item.capacity());// Sting->&strlet i = &item; //&item的类型就是 &str// static'strprintln!("{}", rust_say());// 创建&str的两种方法:const C_S: &str = "";let yzzy = "yzzy";// &str => &u8println!("u8 to String: {}", u8_to_string(yzzy.as_bytes()));// &u8的打印for item in yzzy.as_bytes() {println!("item {}", item);}
}
编译及运行
cargo run
warning: unused variable: `i`--> src/main.rs:31:9|
31 | let i = &item; //&item的类型就是 &str| ^ help: if this is intentional, prefix it with an underscore: `_i`|= note: `#[warn(unused_variables)]` on by defaultwarning: constant `C_S` is never used--> src/main.rs:36:11|
36 | const C_S: &str = "";| ^^^|= note: `#[warn(dead_code)]` on by defaultwarning: `data_struct` (bin "data_struct") generated 2 warningsFinished `dev` profile [unoptimized + debuginfo] target(s) in 0.00sRunning `target/debug/data_struct`
String : cap 0
String c: cap 8
String : cap 10
String hello world: cap 11
String hello world: cap 11
Rust said "str" is danger
u8 to String: yzzy
item 121
item 122
item 122
item 121
二、元组与数组
元组与数组都是有所有权的数据类型
元组与数组都属于序列类型的复合结构
·元组
- 可以包含各种类型值的组合
数组
- 包含同一类型的数据组合
数组注意和切片的关系
fn u8_to_string(string_data: &[u8]) -> String {string_data.iter().map(|&s| s as char).collect()
}#[derive(Debug)]
struct User {name: String,age: i32,
}fn main() {// 元组let tup = (1,2,"hello",User {name: "y".to_owned(),age: 45,},);println!("tup {} {} {} {:?}", tup.0, tup.1, tup.2, tup.3);let (a, b, c, d) = tup;println!("a {} b {} c {} d {:#?}", a, b, c, d);// 数组let my_array = [1, 2, 3, 4];// let my_array: [i32;4] = [1,2,3,4];// let my_array: [i32;3] = [1, 2, 3];// 数组与切片let my_slice = &my_array[1..3];println!("my_array len {}", my_array.len());println!("my_slice len {}", my_slice.len());let u8_array = [121u8, 122u8, 122u8, 121u8];// &u8let u8_slice_ref = &u8_array[0..4]; //&[u8]// &u8_array u8_slice_ref 和 &u8_array是没有区别的println!("{:#?}", u8_to_string(&u8_array));println!("{:#?}", u8_to_string(u8_slice_ref));
}
编译及运行
cargo run Compiling data_struct v0.1.0 (/home/wangji/installer/rust/data_struct/data_struct)
warning: fields `name` and `age` are never read--> src/main.rs:7:5|
6 | struct User {| ---- fields in this struct
7 | name: String,| ^^^^
8 | age: i32,| ^^^|= note: `User` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis= note: `#[warn(dead_code)]` on by defaultwarning: `data_struct` (bin "data_struct") generated 1 warningFinished `dev` profile [unoptimized + debuginfo] target(s) in 16.01sRunning `target/debug/data_struct`
tup 1 2 hello User { name: "y", age: 45 }
a 1 b 2 c hello d User {name: "y",age: 45,
}
my_array len 4
my_slice len 2
"yzzy"
"yzzy"
参考
- Rust常用数据结构教程