Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

字符串

Move 语言提供了两种字符串类型:std::string::String(UTF-8 编码)和 std::ascii::String(ASCII 编码)。两者的底层都是 vector<u8> 的封装,但在编码验证和使用场景上有所不同。UTF-8 字符串是日常开发中最常用的字符串类型,而 ASCII 字符串适用于需要严格限制字符范围的场景。

UTF-8 字符串

创建字符串

std::string::String 是最常用的字符串类型,支持完整的 UTF-8 字符集:

module book::string_create;

use std::string::{Self, String};

#[test]
fun create() {
    // 最常用的方式:字节字面量转换
    let s1: String = b"Hello, Sui!".to_string();

    // 通过 string::utf8 函数创建
    let bytes = b"Hello";
    let s2 = string::utf8(bytes);

    assert_eq!(s1.length(), 11);
    assert_eq!(s2.length(), 5);
}

安全创建

string::try_utf8 返回 Option<String>,在输入不是合法 UTF-8 时不会 abort,而是返回 none

module book::string_safe;

use std::string;

#[test]
fun try_utf8() {
    let valid = string::try_utf8(b"valid utf8");
    assert!(valid.is_some());

    let invalid = string::try_utf8(vector[0xFF, 0xFE]);
    assert!(invalid.is_none());
}

常用字符串操作

拼接与子串

module book::string_ops;

use std::string::String;

#[test]
fun ops() {
    let mut str = b"Hello".to_string();
    let world = b", World!".to_string();

    // 拼接(会修改原字符串)
    str.append(world);
    assert_eq!(str, b"Hello, World!".to_string());
    assert_eq!(str.length(), 13);

    // 提取子串(按字节索引)
    let hello = str.sub_string(0, 5);
    assert_eq!(hello, b"Hello".to_string());

    let world_part = str.sub_string(7, 13);
    assert_eq!(world_part, b"World!".to_string());
}

长度与空值检查

module book::string_check;

use std::string::String;

#[test]
fun length() {
    let s = b"Sui Move".to_string();
    assert_eq!(s.length(), 8);
    assert!(!s.is_empty());

    let empty: String = b"".to_string();
    assert_eq!(empty.length(), 0);
    assert!(empty.is_empty());
}

获取底层字节

bytes() 方法返回字符串底层 vector<u8> 的不可变引用:

module book::string_bytes;

use std::string::String;

#[test]
fun bytes() {
    let s: String = b"ABC".to_string();
    let bytes: &vector<u8> = s.bytes();

    assert_eq!(bytes.length(), 3);
    assert_eq!(bytes[0], 65);  // 'A' 的 ASCII 值
    assert_eq!(bytes[1], 66);  // 'B'
    assert_eq!(bytes[2], 67);  // 'C'
}

插入与删除

module book::string_insert;

use std::string::String;

#[test]
fun insert() {
    let mut s = b"Hello World".to_string();

    // insert: 在指定字节位置插入另一个字符串
    s.insert(5, b",".to_string());
    assert_eq!(s, b"Hello, World".to_string());
}

UTF-8 的限制

length() 返回的是 字节数,而非字符数。对于多字节 UTF-8 字符(如中文),字节数和字符数不同:

module book::string_utf8_limit;

use std::string::String;

#[test]
fun utf8_length() {
    let ascii_str: String = b"Hello".to_string();
    assert!(ascii_str.length() == 5);  // 5 个 ASCII 字符 = 5 字节

    // 注意:sub_string 按字节索引操作
    // 如果在多字节字符的中间截断,会导致非法 UTF-8
    // 因此在处理非 ASCII 字符时需格外小心
}

注意:Move 的字符串 API 基于字节操作,不支持字符级别的访问。在处理包含非 ASCII 字符(如中文、emoji)的字符串时,需要特别注意字节边界问题。

ASCII 字符串

创建和使用

std::ascii::String 严格限制每个字节在 0~127 范围内:

module book::ascii_example;

use std::ascii;

#[test]
fun ascii() {
    // 使用 to_ascii_string 创建
    let s = b"Hello, ASCII!".to_ascii_string();
    assert!(ascii::length(&s) == 13);

    // 安全创建:返回 Option
    let valid = ascii::try_string(b"valid");
    assert!(valid.is_some());

    // 包含非 ASCII 字节的输入会返回 none
    let invalid = ascii::try_string(vector[200u8]);
    assert!(invalid.is_none());
}

UTF-8 与 ASCII 的选择

特性std::string::Stringstd::ascii::String
编码UTF-8ASCII (0~127)
字符范围全 Unicode仅英文字母、数字、基本符号
底层类型vector<u8>vector<u8>
常见用途用户输入、显示文本标识符、协议字段
创建方式b"...".to_string()b"...".to_ascii_string()

在大多数场景下,推荐使用 UTF-8 的 std::string::String。ASCII 字符串主要用于那些需要严格限制字符范围的场景,例如 URL、标识符等。

字符串与字节向量的转换

字符串本质上是带有编码验证的 vector<u8> 封装:

module book::string_conversion;

use std::string::{Self, String};

#[test]
fun conversion() {
    // 字节向量 -> 字符串
    let bytes = b"Hello";
    let s: String = string::utf8(bytes);

    // 字符串 -> 字节向量引用
    let bytes_ref: &vector<u8> = s.bytes();
    assert!(bytes_ref == &b"Hello");

    // 字符串 -> 字节向量(消耗字符串)
    let owned_bytes: vector<u8> = s.into_bytes();
    assert!(owned_bytes == b"Hello");
}

完整示例

module book::string_example;

use std::string::String;

#[test]
fun string_example() {
    let mut str = b"Hello".to_string();
    let world = b", World!".to_string();

    // 拼接
    str.append(world);
    assert_eq!(str.length(), 13);

    // 子串
    let hello = str.sub_string(0, 5);
    assert_eq!(hello, b"Hello".to_string());

    // 空值检查
    assert!(!str.is_empty());

    // 安全创建
    let valid = std::string::try_utf8(b"valid utf8");
    assert!(valid.is_some());

    // 获取字节
    let bytes: &vector<u8> = str.bytes();
    assert_eq!(bytes.length(), 13);
}

小结

字符串是 Move 中处理文本数据的核心类型。本节核心要点:

  • 两种字符串std::string::String(UTF-8)和 std::ascii::String(ASCII)
  • 底层结构:都是 vector<u8> 的封装,带有编码验证
  • 创建方式b"text".to_string() 创建 UTF-8,string::try_utf8() 安全创建
  • 常用操作append() 拼接、sub_string() 子串、length() 长度、is_empty() 检查空值
  • 字节访问bytes() 获取底层字节引用,into_bytes() 转换为字节向量
  • UTF-8 限制length() 返回字节数而非字符数,无字符级别访问
  • ASCII 字符串:适用于标识符等需要限制字符范围的场景
  • 选择建议:大多数情况下使用 UTF-8 字符串