0
点赞
收藏
分享

微信扫一扫

rust UTF-8 & 索引

由于 String 都是 UTF-8 编码的,这会带来几个影响:

如果你需要的是非 UTF-8 字符串,可以考虑 OsString

无法通过索引的方式访问一个 String

具体请看字符串索引。

4. 🌟🌟🌟 我们无法通过索引的方式访问字符串中的某个字符,但是可以通过切片的方式来获取字符串

的某一部分 &s1[start..end]

// 填 空 并 修 复 错 误

fn main() {

let s = String::from("hello, 世 界");

let slice1 = s[0]; //提 示: `h` 在 UTF-8 编 码 中 只 占 用 1 个 字 节

assert_eq!(slice1, "h");

let slice2 = &s[3..5];// 提 示: `世` 在 UTF-8 编 码 中 占 用 3 个 字 节

assert_eq!(slice2, "世");

// 迭 代 s 中 的 所 有 字 符

for (i, c) in s.__ {

if i == 7 {

assert_eq!(c, '世')

}

}

println!("Success!")

}

utf8_slice

我们可以使用 utf8_slice 来按照字符的自然索引方式对 UTF-8 字符串进行切片访问,与之前的切片方式相

比,它索引的是字符,而之前的方式索引的是字节.

示例

use utf8_slice;

fn main() {

let s = "The 🚀 goes to the 🌑!";

let rocket = utf8_slice::slice(s, 4, 5);

// Will equal "🚀"

}

5. 🌟🌟🌟

提示: 也许你需要使用 from_utf8 方法

// 填 空

fn main() {

let mut s = String::new();

__;

let v = vec![104, 101, 108, 108, 111];

// 将 字 节 数 组 转 换 成 String

let s1 = __;

assert_eq!(s, s1);

println!("Success!")

}

内部表示

事实上 String 是一个智能指针,它作为一个结构体存储在栈上,然后指向存储在堆上的字符串底层数

据。

存储在栈上的智能指针结构体由三部分组成:一个指针只指向堆上的字节数组,已使用的长度以及已分配

的容量 capacity (已使用的长度小于等于已分配的容量,当容量不够时,会重新分配内存空间)。

6. 🌟🌟 如果 String 的当前容量足够,那么添加字符将不会导致新的内存分配

// 修 改 下 面 的 代 码 以 打 印 如 下 内 容:

// 25

// 25

// 25

// 循 环 中 不 会 发 生 任 何 内 存 分 配

fn main() {

let mut s = String::new();

println!("{}", s.capacity());

for _ in 0..2 {

s.push_str("hello");

println!("{}", s.capacity());

}

println!("Success!")

}

7. 🌟🌟🌟

// 填 空

use std::mem;

fn main() {

let story = String::from("Rust By Practice");

// 阻 止 String 的 数 据 被 自 动 drop

let mut story = mem::ManuallyDrop::new(story);

let ptr = story.__();

let len = story.__();

let capacity = story.__();

assert_eq!(16, len);

// 我 们 可 以 基 于 ptr 指 针 、 长 度 和 容 量 来 重 新 构 建 String.

// 这 种 操 作 必 须 标 记 为 unsafe, 因 为 我 们 需 要 自 己 来 确 保 这 里 的 操 作 是 安 全 的

let s = unsafe { String::from_raw_parts(ptr, len, capacity) };

assert_eq!(*story, s);

println!("Success!")

}

举报

相关推荐

0 条评论