• 【编程】Rust语言入门第4篇 字符串


    Rust 中的字符是 Unicode 类型,因此每个字符占据 4 个字节内存空间,但字符串不一样,字符串是 UTF-8 编码,也就是字符串中的字符所占的字节数是变化的(1 - 4)。
    常见的字符串有两种:

    1. str,通常是引用类型,&str,即字符串字面常量,字符串切片。
    2. std::string::String
      类型&str的变量是被硬编码的,快速而高效,但不可变;类型String,是可设可变的,它是在堆上的变量,如何管理内存,有的语言用垃圾回收机制(Garbage Collection),标记使用情况并自动清理;而Rust不愿意用GC,既要高性能,又要高安全性,提出变量离开作用域即自动释放其占用的内存,比GC思路更妙。
      C语言中清理内存的函数free,要被手动调用;Rust中则是drop(),Rust自动调用。
      C++中的Resoure Acquisition Is Initialization,RAII模型。

    两种字符串类型互转

    &strString:

    let a = String::from("hello, world");
    "hello, world".to_string();
    
    • 1
    • 2

    String&str,引用即可

    fn main() {
        let s = String::from("hello,world!");
        say_hello(&s);
        say_hello(&s[..]);
        say_hello(s.as_str());
    }
    
    fn say_hello(s: &str) {
        println!("{}",s);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    除上述两种类型,Rust标准库还有其他类型的字符串。

    字符串不能被直接索引

    Rust字符串不允许索引操作。由于不同字符占用字节数不等,考虑操作时间复杂度不能实现O(1)。

    //三个字节
    let a = "中国人";
    //一个字节
    let b = "Chinese";
    
    • 1
    • 2
    • 3
    • 4

    Rust字符串虽然不能索引但可以切片(slice),类似Python等语言中的切片概念。

    fn main() {
        let my_name = "kirk zhang";
        let first_name = &my_name[0..4];
        let last_name = &my_name[5..10];
        println!("{}",first_name);
        println!("{}",last_name);
        greet(String::from(my_name));
        // 尝试my_name[0]报错,不过可以用.chars().nth或.bytes()来实现
        println!("can str be indexed {:?}",my_name.chars().nth(0));
    }
    
    fn greet(name: String){
        println!("hello {}", name);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    小心字符串切片

    注意字符串切片是按字节来的哦,而Rust字符串是UTF-8协议格式,一般1个字符1个字节,但1个中文字符占3个字节;如果切片起止不在字符边界,则有异常。

    fn main(){
        let f = "中国人";
        let f1 = &f[0..5];
        println!("watch out, what you got {}",f1);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    提示:thread ‘main’ panicked at ‘byte index 5 is not a char boundary; it is inside ‘国’ (bytes 3…6) of 中国人’, src/main.rs:10:15
    note: run with RUST_BACKTRACE=1 environment variable to display a backtrace

    字符串的操作

    替换

    replace(要被替换的子串,新字符串),返回结果字符串。

        let word = String::from("rust");
        let new_word = word.replace("r","R");
        println!("{}", new_word);
    
    • 1
    • 2
    • 3

    插入

    insert(位置索引,字符)、insert_str(位置索引,字符串):变量本身变化,声明时要mut。

        let word = String::from("rust");
        let mut new_word = word.replace("r","R");
        new_word.insert_str(0, "I love ");
        println!("{}", new_word);
    
    • 1
    • 2
    • 3
    • 4

    追加

    push(字符)
    push_str(字符串)

        let word = String::from("rust");
        let mut new_word = word.replace("r","R");
        new_word.insert_str(0, "I love ");
        new_word.push('!');
        println!("{}", new_word);   
    
    • 1
    • 2
    • 3
    • 4
    • 5

    连接

    ++= 调用了String的add(self,&str)方法,其定义要求+后面的参数为字符串字面常量,返回String类型。
    或用format! ,适用于 String 和 &str 。format! 的用法与 println! 的用法类似。

    let a1 = String::from("tic");
    let a2 = String::from("tac");
    let a3 = String::from("toe");
    
    // 经过下面一行后,a1被释放了,不能再使用!a2、a3依然存在。
    let s = s1 + "-" + &s2 + "-" + &s3;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    删除

    有4个方法,pop()、remove(索引位置)、truncate(起始位置)、clear()
    注意删除字符串的索引必须是字符串中字符的边界,否则错误。

    fn main() {
        let mut string_remove = String::from("测试remove方法");
        println!(
            "string_remove 占 {} 个字节",
            std::mem::size_of_val(string_remove.as_str())
        );
        // 删除第一个汉字
        string_remove.remove(0);
        // 下面代码会发生错误
        // string_remove.remove(1);
        // 直接删除第二个汉字
        // string_remove.remove(3);
        dbg!(string_remove);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    字符串的字符与字节

    例,

       for c in "中国人".chars() {
           println!("{}", c);
       }
       for b in "中国人".bytes() {
           println!("{}", b);
       }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • 相关阅读:
    win和linux动静态链接库介绍,以及win下动态库生成和调用方法
    vue数组中的变更方法和替换方法
    企业python面试题
    2023年5月CSDN客服月报|解决5个重大问题和18个次要问题,采纳1个用户建议,处理2个用户需求
    【招银网络科技java面试题目面试经验】-看准网
    Mac 使用 scp 上传或下载文件/文件夹
    一个独特的开源插件evil.js
    贷款行业怎么获取高效精准客户
    排序算法之计数排序
    摄像头种类繁多,需要各自APP
  • 原文地址:https://blog.csdn.net/CSUzhangpeike/article/details/136113811