RUST 学习日记 第16课 ——字符串的常用方法(二)

RUST 学习日记 第16课 ——字符串的常用方法(二)


0x00 回顾与开篇

上节课介绍了Rust的字符串常见的修改方法这节课开始介绍Rust字符串的访问方法。介绍Rust字符串的文章,这已经是第4篇了。后续如果还有时间,我会更加详细的在介绍下字符串的一些其它知识。

0x01 Unicode和UTF-8

在计算机中最常见的编码应该就是ASCII编码了,但是ASCII编码的范围只有0x000x7F,无法存储汉字,少数民族文字等等。从而出现了GB2312,GB18030等各种编码。为了统一字符编码,国际标准化组织制定了通用的多字节编码字符集,也就是**Unicode**字符集。其包含了所有世界上所有的语言和各种字符。其中最常用的范围是0x00000xD7FF和0xE000~0x10FFFF。

但是Unicode字符集每个字符都占4个字节,为了节省空间,UTF-8是最简单且高效的一种编码格式。在Rust中String和&str类型都是使用UTF-8编码格式表示文本。UTF-8是以1字节为编码单位的可变长编码,它根据一定规则将码位编码为1~4字节。如下表所示:

UTF-8编码(1~4字节) 码点表示 uNICODE范围
0xxxxxxx 0bxxxxxxx 0x00~0x7f
110xxxxx 10aaaaaa 0bxxxxxaaaaaa 0x80~0x7ff
1110xxxx 10aaaaaa 10bbbbbb 0bxxxaaaaaabbbbbb 0x800~0xffff
11110xxx 10aaaaaa 10bbbbbb 10cccccc 0bxxxaaaaaabbbbbbcccccc 0x10000~0x10ffff

这就很好理解上节所说的汉字占3个字节,而英文字母,阿拉伯数字占1个字节的原因了。

UTF-8编码举例如下:

UTF-8编码(1~4字节) 字符 码点
01100001 a 0b1100001 == 0x61
11000010_10101001 © 0b00010_101001 == 0xa9
11100110_10110001_10001001 0b0110_110001_001001 == 0x6c49
11110000_10011111_10011000_10000011 😃 0b000_011111_011000_000011== 0x1f603

示例代码如下:

println!("***************1、编码*****************");
    let a = "a";
    let b = "©";
    let c = "汉";
    let d = "😃";

    println!("a 占 {} 个字节", std::mem::size_of_val(a));
    println!("b 占 {} 个字节", std::mem::size_of_val(b));
    println!("c 占 {} 个字节", std::mem::size_of_val(c));
    println!("d 占 {} 个字节", std::mem::size_of_val(d));

    println!("\n***************1、编码(打印二进制)*****************");
    for x in a.bytes() {
        print!("{:08b}_", x);
    }
    println!();
    for x in b.bytes() {
        print!("{:08b}_", x);
    }
    println!();
    for x in c.bytes() {
        print!("{:08b}_", x);
    }
    println!();
    for x in d.bytes() {
        print!("{:08b}_", x);
    }

    println!("\n***************1、编码(打印Unicode)*****************");
    println!("{:X}", 'a' as i32);
    println!("{:X}", '©' as i32);
    println!("{:X}", '汉' as i32);
    println!("{:X}", '😃' as i32);

代码运行结果:

***************1、编码*****************
a 占 1 个字节
b 占 2 个字节
c 占 3 个字节
d 占 4 个字节

***************1、编码(打印二进制)*****************
01100001_
11000010_10101001_
11100110_10110001_10001001_
11110000_10011111_10011000_10000011_
***************1、编码(打印Unicode)*****************
61
A9
6C49
1F603

编码和解码规则这里就不赘述了,感兴趣的可以搜索下资料。如果留言比较多,我回额外一章讲解下编码解码。

0x02 字符串的访问

在Rust中,字符串的访问要注意以下两个点:

1、由于字符串是UTF-8编码的字节序列,是可变长度编码,所以不能直接使用索引来访问字符。

2、字符串操作分为按字节处理按字符处理两种方式。使用bytes()方法是按字节处理,返回字节迭代的迭代器。使用chars()方法是按字符处理,返回字符迭代的迭代器。

字符串的长度

如果通过len()方法获取字符串的长度,则返回的是以字节为单位的长度,即字符串中所有字符的总字节数。如果通过chars().count()方法获取的长度则表示字符的长度,通过此方法获取的长度就是咱们嘴上常说的字符串长度啦。

示例代码如下:

let string_length = "我正在学习Rust~";
println!("\"{}\"的字节长度 : {}", string_length, string_length.len());
println!("\"{}\"的字符长度 : {}", string_length, string_length.chars().count());

代码运行结果:

"我正在学习Rust~"的字节长度 : 20
"我正在学习Rust~"的字符长度 : 10
访问字符串元素

由于Rust的字符串是UTF-8编码,所以不允许直接使用索引来访问单个字符元素。那么咱们只能借助迭代器来访问。(有关迭代器的相关知识将在后续章节介绍)bytes()char()方法分别返回字节和字符迭代器,他们中存在nth方法可以通过索引的形式去访问元素。该方法返回的是Option类型。

示例代码如下:

let string_nth = "Rust编程基础";

// 访问第5个字符
dbg!(string_nth.chars().nth(5));
// 访问第5个字节
dbg!(string_nth.bytes().nth(5));

代码运行结果:

[src\main.rs:45] string_nth.chars().nth(5) = Some(
    '程',
)
[src\main.rs:47] string_nth.bytes().nth(5) = Some(
    188,
)

0x03 小结

花了4篇文章也只是简单介绍了Rust的字符串,要想真正的了解字符串的方法,还需要多练习。其实关于Rust字符串的知识和相关方法还是挺多的,由于篇幅有限,字符串的讲解就暂告一段落了。

0x05 参考资料

Unicode所有区段 统一码编码范围 | Unicode符号库 ✏️ (fuhaoku.net)

0x04 本节源码

016 · StudyRust - 码云 - 开源中国 (gitee.com)

下节预告——流程控制。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,163评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,301评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,089评论 0 352
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,093评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,110评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,079评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,005评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,840评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,278评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,497评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,394评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,980评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,628评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,649评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,548评论 2 352