欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 文化 > Rust切片、结构体、枚举

Rust切片、结构体、枚举

2025/4/18 19:34:11 来源:https://blog.csdn.net/ye_yumo/article/details/147016813  浏览:    关键词:Rust切片、结构体、枚举

文章目录

    • 切片类型
      • 字符串切片
      • 其他结构的切片
    • 结构体
      • 结构体实例
      • 元组结构体
      • 结构体所有权
      • 输出结构体
      • 结构体的方法
      • 结构体关联函数
      • 单元结构体
    • 枚举
      • match语法
      • Option枚举类
      • if let 语句

切片类型

切片(Slice)是对数据值的部分“引用”

我们可以从一个数据集合中取一部分来使用

字符串切片

例如

fn main() {let s = String::from("broadcast");let part1 = &s[0..5];let part2 = &s[5..9];println!("{}={}+{}", s, part1, part2);
}

这里的0..5是前闭后开区间实际上内存上是这样的

image.png

有一些简便的写法,可以这样写

..y 等价于 0..y
x.. 等价于位置 x 到数据结束
.. 等价于位置 0 到结束

被切片引用的字符串是不允许被修改的,除此之外,我们需要区分strString这两个字符串类型

前者指的是堆内存中的字符串,我们可以理解为常量字符串,用的时候是作为&str引用使用的

String实际上是一种数据类型,类似于C++中的string类,有追加,清空等一系列操作

这两者都支持切片,切片的结果必须是引用类型

let slice = &s[0..3];

其他结构的切片

fn main() {let arr = [1, 3, 5, 7, 9];let part = &arr[0..3];for i in part.iter() {println!("{}", i);}
}

原理都是类似的

结构体

结构体和元组是类似的,可以将不同类型的数据作为一个整体,但是结构体内部每个成员是有名字的

例如

struct Site {domain: String,name: String,nation: String,found: u32
}

这里的结构体和C++中的不太一样,这里的结构体只能用来定义类型,不能实例化对象,不需要;,成员用,分割

结构体实例

结构体实例化是使用key: value的形式进行赋值的,例如

let baidu = Site {domain: String::from("www.baidu.com"),name: String::from("baidu"),nation: String::from("China"),found: 2013
};

如果当前作用域有和成员变量名称相同的,可以直接写

let domain = String::from("www.baidu.com");
let name = String::from("baidu");
let baidu = Site {domain,  // 等同于 domain : domain,name,    // 等同于 name : name,nation: String::from("China"),traffic: 2013
};

如果用一个结构体实例的一部分去构建另一个结构体,可以这样写

let site = Site {domain: String::from("www.baidu.com"),name: String::from("b"),..baidu
};

但是不允许全部用旧结构体的

元组结构体

元组结构体的定义和使用更为简单,实际上是一种元组形式的结构体,区别就是有名字和固定的类型格式,主要是为了处理定义经常使用的简单类型用的

struct Color(u8, u8, u8);
struct Point(f64, f64);let black = Color(0, 0, 0);
let origin = Point(0.0, 0.0);

使用方法就和普通的元组使用是一样的了

结构体所有权

结构体实例会掌握所有成员的所有权,因为当结构体生命周期结束的时候,会释放所有字段

输出结构体

#[derive(Debug)]
struct Rectangle {width: u32,height: u32,
}fn main() {let rect1 = Rectangle { width: 30, height: 50 };println!("rect1 is {:?}", rect1);
}

第一行是调用调试库,然后用:?做占位符就可以输出整个结构体的内容了,使用:#?就可以自动格式化

结构体的方法

结构体的方法主要是用于操作结构体实例本身的

Rust语言其实不是面向对象的,但是也可以实现面向对象的思想

结构体方法的第一个参数必须是&self,不需要声明类型

例如计算一个矩形的面积

struct Rectangle {width: u32,height: u32,
}impl Rectangle {fn area(&self) -> u32 {self.width * self.height}
}fn main() {let rect1 = Rectangle { width: 30, height: 50 };println!("rect1's area is {}", rect1.area());
}

调用结构体方法的时候就可以不用写self了

结构体关联函数

如果做impl中,但是没有&self参数,而是属于结构体全体的,不属于某个具体的实例

类似于C++中的静态成员函数

#[derive(Debug)]
struct Rectangle {width: u32,height: u32,
}impl Rectangle {fn create(width: u32, height: u32) -> Rectangle {Rectangle { width, height }}
}fn main() {let rect = Rectangle::create(30, 50);println!("{:?}", rect);
}

单元结构体

结构体也可以不需要任何成员

struct UnitStruct;

枚举

Rust的枚举和C++的枚举还是不太一样的,但是使用是比较简单的,例如

#[derive(Debug)]enum Book {Papery, Electronic
}fn main() {let book = Book::Papery;println!("{:?}", book);
}

我们可以给枚举添加元组属性描述,或者使用结构体的语法都是可以的

enum Book {Papery(u32),Electronic(String),
}let book = Book::Papery(1001);
let ebook = Book::Electronic(String::from("url://..."));enum Book {Papery { index: u32 },Electronic { url: String },
}
let book = Book::Papery{index: 1001};

但是我们无法访问具体枚举对应的值是什么,访问的方法在下面介绍

match语法

match很类似switch,但是rust并不支持switch

例如

fn main() {enum Book {Papery {index: u32},Electronic {url: String},}let book = Book::Papery{index: 1001};let ebook = Book::Electronic{url: String::from("url...")};match book {Book::Papery { index } => {println!("Papery book {}", index);},Book::Electronic { url } => {println!("E-book {}", url);}}
}

基本格式是这样的

match 枚举类实例 {分类1 => 返回值表达式,分类2 => 返回值表达式,...
}

但是所有返回值表达式的类型必须是一样的

match除了可以处理枚举,也可以处理整数、浮点数、字符、字符串切片引用的,但是不推荐使用浮点数,有可能有精度问题

默认情况用_表示,例如

fn main() {let t = "abc";match t {"abc" => println!("Yes"),_ => {},}
}

Option枚举类

Option时Rust标准库自带的枚举类,这主要是为了解决Rust没有空引用的问题

Option具体是这样的

enum Option<T> {Some(T),None,
}

我们如果要对这个类型的数据做操作的时候,就必须先判断是否时None

fn main() {let opt = Option::Some("Hello");match opt {Option::Some(something) => {println!("{}", something);},Option::None => {println!("opt is nothing");}}
}

如果我们想要声明某个变量是空值时,就必须先声明明确的类型

fn main() {let opt: Option<&str> = Option::None;match opt {Option::Some(something) => {println!("{}", something);},Option::None => {println!("opt is nothing");}}
}

Option是默认引入的,所以可以直接写Some()或者None

if let 语句

这是一种match语句的语法糖,可以用来简化匹配match枚举类型的yufa

如果直接使用if else

let maybe_name = Some("Alice");if maybe_name {println!("Name is: {}", maybe_name); // ❌ 编译错误:不能直接判断 Option
}

正确的方式是使用if let ,当然这个后面可以加上else

let maybe_name = Some("Alice");if let Some(name) = maybe_name {println!("Name is: {}", name); // ✅ 解构出 name
}

对应的match写法是

match maybe_name {Some(name) => println!("Name is: {}", name),_ => (), // 其它情况忽略
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词