Skip to content

Commit 2cb1ab2

Browse files
authored
Merge branch 'SAST-skill-docers:master' into lecture
2 parents e8a561f + fbc331f commit 2cb1ab2

File tree

3 files changed

+97
-6
lines changed

3 files changed

+97
-6
lines changed

docs/languages/rust/control.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,36 @@ let must_be_one = loop {
8989
}
9090
}; // must_be_one 的值应当为 1
9191
// 如果你发现程序没有结束,请多等一会
92+
```
93+
94+
### 循环标签
95+
96+
如果存在嵌套循环,`break``continue` 都只作用于此时最内层的循环。在Rust中,你可以为特定循环指定 循环标签(loop label),然后将标签与 break 或 continue 一起使用,使这些关键字作用于所标记的循环,实现跳出多重循环的目的。
97+
98+
在有这个特性之前,「跳出多重循环」其实颇为棘手——因为最优雅的方式是声名狼藉的"goto"。虽然「把循环封装在一个函数内用return跳出」是个好办法,但并不总适合这样做。
99+
100+
```rust
101+
let matrix = vec![
102+
vec![1, 2, 3],
103+
vec![4, 5, 6],
104+
vec![7, 8, 9]
105+
];
106+
107+
let target = 5;
108+
let mut found = false;
109+
110+
'outer: for row in &matrix { // 将循环标签放在循环前面. 格式为 'label
111+
for &num in row {
112+
if num == target {
113+
found = true;
114+
break 'outer; // 使用循环标签直接跳出外层循环
115+
}
116+
}
117+
}
118+
119+
if found {
120+
println!("找到了目标元素!");
121+
} else {
122+
println!("未找到目标元素。");
123+
}
92124
```

docs/languages/rust/index.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@
1616

1717
不同于 JavaScript 和 Python 等语言,Rust 语言上手相对较为困难。因此,编写本文档的目的更类似于在假定读者拥有一定 C++ 基础的情况下,向读者提供一些学习 Rust 的对照性帮助,而非一个 Rust 入门教程。如果希望获得一份 Rust 入门教程,请参阅下方资源链接中的 The Book。
1818

19+
本文档覆盖了 The Book 的 第3(常见编程概念)、5(结构体)、6(枚举和模式匹配)章的主要内容,介绍了最为基本的语法,且不怎么涉及新概念(如所有权、生命周期)。
20+
1921
## 资源链接
2022

2123
- The Rust Programming Language(也被称为 The Book)。Rust 官方网站推荐的 Rust 语言入门书籍 https://doc.rust-lang.org/book/
22-
- The Book 的中文社区翻译版,版本可能落后于英文原版 https://rustwiki.org/zh-CN/book/
24+
- The Book 的中文社区翻译版,更新很及时 https://kaisery.github.io/trpl-zh-cn/
2325

2426
- Rustlings。Rust 官方推荐的另一种入门方式,适合喜欢边学边做的同学 https://github.com/rust-lang/rustlings/

docs/languages/rust/variable.md

Lines changed: 62 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
# Rust 的变量与类型
22

3-
!!! caution
4-
5-
本页尚未完工
6-
73
## 变量声明
84

95
Rust 语言中通过 `let` 关键字来声明变量。Rust 是一门静态强类型语言,因此任何一个变量都有一个确定、不可变的类型。如果在声明同时初始化,则可以依靠编译器的类型推断来得到变量类型,不一定需要显式指定类型。
@@ -41,6 +37,8 @@ a = 2; // 变量 a 可变,OK
4137

4238
这种说法是不严格的,但是这样思考可以快速上手。
4339

40+
Rust 的这种设计看似奇怪,其实也有其用意。一般大部分变量的值实际上都不需要修改,默认不可变可以强制程序员思考变量是否需要修改,从而避免了一些潜在的错误。而在 C++ 中想达到相同的效果,则需要主动使用大量 `const` 关键字,其繁琐会让大部分程序员不愿意这么做。
41+
4442
!!! note "如何打印一个变量"
4543

4644
```rust
@@ -50,6 +48,43 @@ a = 2; // 变量 a 可变,OK
5048

5149
这里的 `println!` 是一个宏,但使用起来与函数很相似。
5250

51+
### 常量
52+
53+
Rust 中的常量使用 `const` 关键字声明,常量的值必须在编译期间确定。常量的类型必须显式指定。
54+
55+
```rust
56+
const SECONDS_PER_DAY: i32 = 24 * 60 * 60; // 常量的值必须在编译期间确定. 能够通过编译
57+
// const B = 1; // 常量必须显式指定类型,编译无法通过
58+
const c: i32 = 1; // 能够通过编译,但会被编译器警告,因为常量名的规范是 大写字母+下划线
59+
```
60+
61+
!!! note "与 C++ 的对照"
62+
63+
Rust 的 `const` 在定位上和 C++ 的 `constexpr` 基本是一致的。
64+
65+
C++ 中,一般把 `const` 与 `constexpr` 所定义的量都笼统地称为“常量”。但从 Rust 的视角看,只有编译期常量才是真正的“常量”,而 C++ 中用 `const` 声明的所谓“常量”在语义上只是一个“不可变量”(readonly,只读),其实反而更接近 变量 而不是 常量。
66+
67+
也许可以这样理解:常量是一个「值」;而变量是一个「对象」、其值可能要在运行时才能确定,而这个变量是否可变则是另一个回事。
68+
69+
例如,定义数组要求数组的长度必须是常量表达式。但 C++ 中 `const` 声明的所谓“常量”并不一定能满足这点;而 C++ 中的 `constexpr` 与 Rust 中的 `const` 则都能满足。
70+
71+
### 变量遮蔽
72+
73+
其英文为 `shadowing`,可被译为“遮蔽”、“重影”,是 Rust 的一种特殊语法,允许在同一作用域中声明一个与之前变量同名的新变量,从而遮蔽之前的变量。
74+
75+
这相当于把变量名绑定到了一个新的值上,而不是修改了原来的值。这种特性在一些场景下很有用,可以减少变量的数量、减轻给变量取名字的负担。
76+
77+
```rust
78+
let spaces = " "; // spaces 是一个字符串
79+
let spaces = spaces.len(); // spaces 变成了一个数字
80+
81+
let mut spaces = " "; // spaces 是一个字符串
82+
// spaces = spaces.len(); // 编译无法通过,因为 spaces 已经是一个字符串,不能再赋值为数字,类型不匹配
83+
84+
let mut num = 1;
85+
num *= 2; // OK
86+
```
87+
5388
## 变量类型
5489

5590
### 基本类型
@@ -149,7 +184,29 @@ let arr_long: [i32; 100] = [0; 100];
149184

150185
!!! note "与 C++ 的对照"
151186

152-
Rust 的数组可以直接作为参数传递,这一点与 C/C++ 不同(C++ 中的 `std::tuple` 与 Rust 的数组更加类似)。与 C/C++ 类似的是,数组的长度都是不可变的,变长的线性容器在两门语言中分别叫做 `std::Vec` 和 `std::vector`。
187+
Rust 的数组可以直接作为参数传递,这一点与 C/C++ 不同(C++ 中的 `std::tuple` 与 Rust 的数组更加类似)。这是因为 Rust 的数组是在栈上分配的。与 C/C++ 类似的是,数组的长度都是不可变的,变长的线性容器在两门语言中分别叫做 `std::Vec` 和 `std::vector`。
188+
189+
Rust 的下标访问自带越界检查。
190+
191+
下面的代码将会在编译时报错:
192+
193+
```rust
194+
let arr = [1, 2, 3];
195+
let element = arr[3]; // 编译器报错:index out of bounds: the length is 3 but the index is 3
196+
```
197+
198+
下面的代码能够通过编译,但当输入的下标超出数组长度时,程序会立即退出而不允许访问越界的内存:
199+
200+
```rust
201+
use std::io;
202+
203+
let arr = [1, 2, 3];
204+
let mut index = String::new();
205+
io::stdin().read_line(&mut index).expect("Failed to read line"); // 若输入10...
206+
let index: usize = index.trim().parse().expect("Index must be a number");
207+
let element = arr[index]; // ...程序产生运行时错误并退出
208+
println!("The value of element is: {}", element); // 该行不会被执行
209+
```
153210

154211
### 单元类型
155212

0 commit comments

Comments
 (0)