30天拿下Rust之切片

这篇具有很好参考价值的文章主要介绍了30天拿下Rust之切片。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

概述

        在Rust中,切片是一种非常重要的引用类型。它允许你安全地引用一段连续内存中的数据,而不需要拥有这些数据的所有权。切片不包含分配的内存空间,它仅仅是一个指向数据开始位置和长度的数据结构。切片是对数组的一个连续引用,它提供了一种方便、高效的方式来操作数组的一部分。切片本身并不拥有数据,它只是原始数组的一个视图,因此创建切片通常是一个低开销的操作。

切片的声明

        在Rust中,切片的声明格式如下。

let slice_name: [T; n] = &array[start..end];

        下面,我们详细介绍切片声明中的各个元素。

        slice_name:切片变量取的名字。

        [T; n]:是一个泛型,表示一个包含n个类型为T的元素的切片。但在实际声明中,通常不需要指定n,因为Rust会根据初始化的数据自动推断出长度。

        &array[start..end]:创建一个从array中的start索引到end索引(但不包含 end 索引)的切片。start和end是范围操作符..的参数,用于定义切片的开始位置和结束位置(但不包括结束位置)。注意:start索引可以不写,不写时默认为0;end索引也可以不写,不写时默认为array的最后一个元素的索引。

        在下面的示例代码中,我们使用数组的切片操作创建了slice切片,Rust会自动推断出slice切片的类型为:&[i32]。

fn main() {
    let array = [1, 2, 3, 4, 5];
    // 创建一个从索引1到索引4(不包含4)的切片
    let slice = &array[1..4];
    assert_eq!(slice, &[2, 3, 4]);
}

        如果我们要声明一个可变切片,可以使用mut关键字。在下面的示例代码中,&mut表示对原始数组的一个可变引用,这意味着你可以通过这个切片修改原始数组的内容。

fn main() {
    let mut array = [1, 2, 3, 4, 5];
    // 可变切片
    let mutable_slice = &mut array[1..4];
    // 输出:[2, 3, 4]
    println!("{:?}", mutable_slice);
}

        如果我们要声明一个空的切片,可以使用空数组字面量来初始化。在下面的示例代码中,empty_slice是一个空的i32类型切片。注意:我们在这里显式指定了切片的类型,因为空切片本身不包含足够的信息来自动推断类型。

fn main() {
    let empty_slice: &[i32] = &[];
    // 输出:[]
    println!("{:?}", empty_slice);
}

切片的使用

        1、获取切片的长度,可以使用len()方法。

fn main() {
    let text = "Hello, CSDN";
    let word = &text[0..5];
    let len: usize = word.len();
    // 输出: 5
    println!("{}", len);
}

        2、切片可以通过索引来访问其内部元素。切片的索引遵循与数组相同的规则:从0开始,并且是基于半开区间[start, end)的原则,即:包含起始索引,但不包含结束索引。

fn main() {
    let numbers = [1, 2, 3, 4, 5];
    let slice: &[i32] = &numbers[2..];
    // 输出:3
    println!("{}", slice[0]);

    let mut mut_numbers = [1, 2, 3, 4, 5];
    let mut_slice: &mut [i32] = &mut mut_numbers[1..];
    // 修改切片中的元素
    mut_slice[0] *= 10;
    // 原始数组会被修改,输出:20
    println!("{}", mut_numbers[1]);
}

        注意:索引操作不会进行越界检查,如果尝试访问超出切片范围的索引,将导致运行时错误。为了安全地访问切片元素,可以使用get()方法。

fn main() {
    let numbers = [1, 2, 3, 4, 5];
    let slice: &[i32] = &numbers[2..];
    // 安全访问切片元素
    if let Some(value) = slice.get(1) {
        // 输出:element is: 4
        println!("element is: {}", value);
    } else {
        println!("out of bounds");
    }
}

        3、切片可以通过迭代器来进行遍历。我们可以使用for循环配合.iter()方法来迭代不可变切片中的元素,或者使用.iter_mut()方法来迭代可变切片中的元素。

fn main() {
    let numbers = [1, 2, 3, 4, 5];
    let slice: &[i32] = &numbers[2..];
    // 输出:3 4 5
    for number in slice.iter() {
        println!("{}", number);
    }

    let mut mut_numbers = [1, 2, 3, 4, 5];
    let mut_slice: &mut [i32] = &mut mut_numbers[..];
    // 修改切片中的元素
    for number in mut_slice.iter_mut() {
        *number *= 10;
    }

    // 输出:[10, 20, 30, 40, 50]
    println!("{:?}", mut_numbers);
}

        4、字符串切片(&str)可以通过chars()方法来迭代其中的Unicode字符。这是因为:Rust中的字符串是UTF-8编码的,而一个Unicode字符可能由1到4个字节组成。chars()方法会返回一个实现了Iterator trait的结构体,每次迭代都会返回一个char类型的值。

fn main() {
    let slice = "Hello, 霸都";
    for c in slice.chars() {
        println!("{}", c);
    }
}

        另外,字符串切片还包括非常多实用的方法。

        is_empty():检查字符串切片是否为空。

        bytes():返回一个迭代器,可以遍历字符串字节。

        starts_with(&prefix)、ends_with(&suffix):检查字符串切片是否以指定前缀或后缀开始/结束。

        find(subslice):查找子字符串,并返回其索引(如果存在);否则,返回None。

        contains(char) 、contains(&str):检查字符串切片中是否存在指定字符或子字符串。

        split(char)、split_whitespace():根据指定分隔符创建迭代器,每次迭代返回一个新字符串切片。

        trim()、trim_start()、trim_end():移除字符串切片开头、结尾处的空白字符。

        to_lowercase()、to_uppercase():转换为小写或大写字母形式。

        这些方法具体如何使用,可参考下面的示例代码。

fn main() {
    let slice: &str = "";
    assert!(slice.is_empty());

    for c in "Hello, 中国".chars() {
        println!("{}", c);
    }

    for byte in "hello, 中国".bytes() {
        println!("{}", byte);
    }

    let slice: &str = "Hello, CSDN";
    assert!(slice.starts_with("Hello"));
    assert!(slice.ends_with("CSDN"));

    let index = "Hello, CSDN".find(",");
    assert_eq!(index, Some(5));

    let contains1 = "Hello, CSDN".contains("Hello");
    let contains2 = "Hello, CSDN".contains('D');
    assert!(contains1 && contains2);

    // 输出:Hello和CSDN
    for word in "Hello, CSDN".split(',') {
        println!("{}", word.trim());
    }

    let trimmed = "   Hello, CSDN   ".trim();
    assert_eq!(trimmed, "Hello, CSDN");

    let lowercased = "Hello, CSDN".to_lowercase();
    assert_eq!(lowercased, "hello, csdn");
}

总结

        最后,我们来总结一下切片的特性,主要有以下几点。

        1、引用类型:切片是一种引用类型,它允许我们以引用的方式访问连续内存的数据。

        2、没有所有权:切片本身并不拥有数据,而是对数据的一种引用或视图。这意味着切片不会复制数据,而是直接引用原始数据,没有拷贝数据的额外开销。

        3、连续内存:切片引用的是一段连续的内存分配,而不是整个集合。这使得切片能够安全、高效地访问数组,而无需复制数据。

        4、可变与不可变:切片可以是可变的,也可以是不可变的,这取决于它们所引用的数据的可变性。可变切片允许修改引用的数据,而不可变切片则不允许。

        5、索引与迭代:切片可以使用数字索引来访问其中的元素,索引从0开始计数。此外,切片还支持迭代,可以使用迭代器来遍历切片中的元素。文章来源地址https://www.toymoban.com/news/detail-839466.html

到了这里,关于30天拿下Rust之切片的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 30天拿下Rust之面向对象

    概述         在编程语言的世界中,Rust以其独特的内存安全、并发控制和高性能特性吸引了众多开发者。虽然Rust并非传统的面向对象编程语言(比如:C++、Java),但它依然支持并提供了一种颇具特色的面向对象编程方式,以实现类似于面向对象的编程范式。        

    2024年04月15日
    浏览(28)
  • 30天拿下Rust之Trait

    概述         在Rust中,Trait是一个核心概念,它允许我们定义类型应该具有的行为。Trait类似于其他语言中的接口,但Rust的Trait更为强大和灵活。它不仅定义了一组方法,还允许我们指定方法的默认实现、泛型约束和继承。通过Trait,我们可以定义一组方法的签名和关联类

    2024年03月17日
    浏览(30)
  • 30天拿下Rust之错误处理

    概述         在软件开发领域,对错误的妥善处理是保证程序稳定性和健壮性的重要环节。Rust作为一种系统级编程语言,以其对内存安全和所有权的独特设计而著称,其错误处理机制同样体现了Rust的严谨与实用。在Rust中,错误处理通常分为两大类:不可恢复的错误和可

    2024年03月21日
    浏览(56)
  • 30天拿下Rust之高级类型

    概述         Rust作为一门系统编程语言,以其独特的内存管理方式和强大的类型系统著称。其中,高级类型的应用,为Rust的开发者提供了丰富的编程工具和手段,使得开发者可以更加灵活和高效地进行编程。 Newtype模式         Newtype模式是一种轻量级的设计模式,用

    2024年04月15日
    浏览(34)
  • 30天拿下Rust之HashMap

    概述         HashMap,被称为哈希表或散列表,是一种可以存储键值对的数据结构。它使用哈希函数将键映射到存储位置,以便可以快速检索和更新元素。这种数据结构在许多编程语言中都存在,而在Rust中,它被实现为HashMapK, V。其中,K表示键的类型,V表示值的类型。H

    2024年03月17日
    浏览(32)
  • 30天拿下Rust之生命周期

    概述         在Rust中,生命周期是一个非常重要的概念,是保证内存安全和防止悬垂引用的核心机制之一。通过精确地跟踪引用的生命周期,Rust能够在编译阶段就防止许多其他语言在运行时才会遇到的内存问题。在Rust中,生命周期代表了引用的有效时间段。当我们创建

    2024年03月20日
    浏览(34)
  • 30天拿下Rust之unsafe代码

    概述         在Rust语言的设计哲学中,\\\"安全优先\\\" 是其核心原则之一。然而,在追求极致性能或者与底层硬件进行交互等特定场景下,Rust提供了unsafe。unsafe代码允许开发者暂时脱离Rust的安全限制,直接操作内存和执行低级操作。虽然unsafe代码在某些情况下是必要

    2024年04月17日
    浏览(33)
  • 30天拿下Rust之字符串

    概述         在Rust中,字符串是一种非常重要的数据类型,用于处理文本数据。Rust的字符串是以UTF-8编码的字节序列,主要有两种类型:str和String。其中,str是一个对字符数据的不可变引用,更像是对现有字符串数据的“视图”,而String则是一个独立、可变更的字符串实

    2024年03月12日
    浏览(37)
  • 30天拿下Rust之所有权

    概述         在编程语言的世界中,Rust凭借其独特的所有权机制脱颖而出,为开发者提供了一种新颖而强大的工具来防止内存错误。这一特性不仅确保了代码的安全性,还极大地提升了程序的性能。在Rust中,所有权是一种编译时检查机制,用于追踪哪些内存或资源何时可

    2024年03月08日
    浏览(29)
  • 30天拿下Rust之命令行参数

    概述         在Rust中,命令行参数是程序从命令行接收的输入,它们为程序提供了运行时配置和数据的灵活性。对于需要用户交互或自动化脚本的Rust程序来说,正确地解析命令行参数至关重要。通过std::env::args和第三方库(比如:clap),我们可以轻松地获取和解析命令行

    2024年03月26日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包