Rust中的字符串

已发布 2017-07-07 17:01:09

String

Keywords: dynamic(growable), in heap, Vec like, have ownership, UTF-8 encoded.

It is a encapsulation of the type Vec<u8>.

It is the replacement for the old ~str type, which has now been removed.

str

Keywords: immutable, unknon length, in memory, UTF-8 encoded.

A string literal “foo” is a &str, where the data is hardcoded into the executable and loaded into memory when the program runs.

Since the size is unknown, one can only handle it behind a pointer, meaning that str most commonly appears as &str, which is called slice and the pointer have fixed length.

A slice is just a view onto some data, these data maybe:

  • in static storage
  • heap allocated String
  • on stack in memory

字节、标量值和字形簇

梵文书写的印度语单词“नमस्ते”,最终它储存在Vec中的u8值看起来像这样:

[224, 164, 168, 224, 164, 174, 224, 164, 184, 224, 165, 141, 224, 164, 164, 224, 165, 135]

这里有 18 个字节,也就是计算机最终会储存的数据。如果从 Unicode 标量值的角度理解他们,也就像 Rust 的char类型那样,这些字节看起来像这样:

['न', 'म', 'स', '्', 'त', 'े']

这里有六个char,不过第四个和第六个都不是字母,他们是发音符号本身并没有任何意义。最后,如果以字形簇的角度理解,就会得到人们所说的构成这个单词的四个字母:

["न", "म", "स्", "ते"]

Rust 提供了多种不同的方式来解释计算机储存的原始字符串数据,这样程序就可以选择它需要的表现方式,而无所谓是何种人类语言。

最后一个 Rust 不允许使用索引获取String字符的原因是索引操作预期总是需要常数时间 (O(1))。但是对于String不可能保证这样的性能,因为 Rust 不得不检查从字符串的开头到索引位置的内容来确定这里有多少有效的字符。

如果你需要操作单独的 Unicode 标量值,最好的选择是使用chars方法。对“नमस्ते”调用chars方法会将其分开并返回六个char类型的值,接着就可以遍历结果来访问每一个元素了:

for c in "नमस्ते".chars() {
    println!("{}", c);
}

bytes方法返回每一个原始字节,这可能会适合你的使用场景:

for b in "नमस्ते".bytes() {
    println!("{}", b);
}

这些代码会打印出组成String的 18 个字节

不过请记住有效的 Unicode 标量值可能会由不止一个字节组成。

从字符串中获取字形簇是很复杂的,所以标准库并没有提供这个功能。

Conclusion

The relationship between String and &str is identical to the relationship between a vector Vec<T> and a slice &[T], and is similar to the relationship between by-value T and by-reference &T for general types.

不同的语言选择了不同的向程序员展示其复杂性的方式。Rust 选择了以准确的方式处理String数据作为所有 Rust 程序的默认行为,这意味着程序员们必须更多的思考如何在前台处理 UTF-8 数据。这种权衡取舍相比其他语言更多的暴露出了字符串的复杂性,不过也使你在开发生命周期中免于处理涉及非 ASCII 字符的错误。

补充:Rust中的字符串比想象中的要复杂

Rust 拥有四种字符串类型,每种都用于不同的目的。在每一对中,都有一个“Owned”的字符串类型,和一个“切片”的字符串类型。组织起来像这样:

type “Slice”类型 “Owned”类型
UTF-8 str String
OS 兼容 OsStr OsString
C 兼容 CStr CString
系统路径 Path PathBuf

Rust 的不同字符串类型适用于不同的目的。Stringstr 为 UTF-8 编码的通用目的字符串。OsStringOsStr 的编码取决于当前平台,在与操作系统交互时使用。CStringCStrRust 中与 C 字符串相当的存在,用于 FFI 代码。PathBufPathOsStringOsStr 的方便封装,提供路径操作的特定方法。

comments powered by Disqus