Skip to content

Commit da921ce

Browse files
author
Naupio Z.Y. Huang
committed
rewrite: add 04 chapter (#203)
* fix #160 * rewrite 04 chapter: add 04-00-rust-travel * fix #163 * update 12-01 * add 04-01-primitive-type && update 04-00 * add 04-01-primitive-type && update 04-00 * add 04-01-primitive-type && update 04-00 * update readme * update readme * add 04-02-primitive-type * add 04-03-struct-enum * rewrite: add 04 chapter
1 parent 88d4d33 commit da921ce

8 files changed

Lines changed: 808 additions & 0 deletions
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
04-03-字符串与向量
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# 结构体与枚举
2+
3+
## 结构体
4+
5+
结构体 (struct) 是一种记录类型,所包含的每个域 (field) 都有一个名称。
6+
每个结构体也都有一个名称,通常以大写字母开头,使用驼峰命名法。
7+
元组结构体 (tuple struct) 是由元组和结构体混合构成,元组结构体有名称,
8+
但是它的域没有。当元组结构体只有一个域时,称为新类型 (newtype)。
9+
没有任何域的结构体,称为类单元结构体 (unit-like struct)。
10+
结构体中的值默认是不可变的,需要使用`mut`使其可变。
11+
12+
```rust
13+
// structs
14+
struct Point {
15+
x: i32,
16+
y: i32,
17+
}
18+
let mut point = Point { x: 0, y: 0 };
19+
20+
// tuple structs
21+
struct Color(u8, u8, u8);
22+
let android_green = Color(0xa4, 0xc6, 0x39);
23+
let (red, green, blue) = android_green;
24+
25+
// A tuple struct’s constructors can be used as functions.
26+
struct Digit(i32);
27+
let v = vec![0, 1, 2];
28+
let d: Vec<Digit> = v.into_iter().map(Digit).collect();
29+
30+
// newtype: a tuple struct with only one element
31+
struct Inches(i32);
32+
let length = Inches(10);
33+
let Inches(integer_length) = length;
34+
35+
// unit-like structs
36+
struct Null;
37+
let empty = Null;
38+
```
39+
40+
一个包含`..``struct`可以用来从其它结构体拷贝一些值或者在解构时忽略一些域:
41+
42+
```rust
43+
#[derive(Default)]
44+
struct Point3d {
45+
x: i32,
46+
y: i32,
47+
z: i32,
48+
}
49+
50+
let origin = Point3d::default();
51+
let point = Point3d { y: 1, ..origin };
52+
let Point3d { x: x0, y: y0, .. } = point;
53+
```
54+
55+
需要注意,Rust在语言级别不支持域可变性 (field mutability),所以不能这么写:
56+
57+
```rust
58+
struct Point {
59+
mut x: i32,
60+
y: i32,
61+
}
62+
```
63+
这是因为可变性是绑定的一个属性,而不是结构体自身的。可以使用`Cell<T>`来模拟:
64+
65+
```rust
66+
use std::cell::Cell;
67+
68+
struct Point {
69+
x: i32,
70+
y: Cell<i32>,
71+
}
72+
73+
let mut point = Point { x: 5, y: Cell::new(6) };
74+
75+
point.y.set(7);
76+
```
77+
78+
此外,结构体的域默认是私有的,可以使用`pub`关键字将其设置成公开。
79+
80+
## 枚举
81+
82+
Rust有一个集合类型,称为枚举 (enum),对于一个指定的名称有一组可替代的值,
83+
其中子数据结构可以存储也可以不存储数据,需要使用`::`语法来获得每个元素的名称。
84+
85+
```rust
86+
// enums
87+
enum Message {
88+
Quit,
89+
ChangeColor(i32, i32, i32),
90+
Move { x: i32, y: i32 },
91+
Write(String),
92+
}
93+
94+
let x: Message = Message::Move { x: 3, y: 4 };
95+
```
96+
97+
与结构体一样,枚举中的元素默认不能使用关系运算符进行比较 (如`==`, `!=`, `>=`),
98+
也不支持像`+``*`这样的双目运算符,需要自己实现,或者使用`match`进行匹配。
99+
100+
枚举默认也是私有的,如果使用`pub`使其变为公有,则它的元素也都是默认公有的。
101+
这一点是与结构体不同的:即使结构体是公有的,它的域仍然是默认私有的。
102+
此外,枚举和结构体也可以是递归的 (recursive)。
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
# 操作流
2+
3+
## If
4+
5+
If是分支 (branch) 的一种特殊形式,也可以使用`else``else if`
6+
与C语言不同的是,逻辑条件不需要用小括号括起来,但是条件后面必须跟一个代码块。
7+
Rust中的`if`是一个表达式 (expression),可以赋给一个变量:
8+
9+
```rust
10+
let x = 5;
11+
12+
let y = if x == 5 { 10 } else { 15 };
13+
```
14+
15+
Rust是基于表达式的编程语言,有且仅有两种语句 (statement):
16+
17+
1. **声明语句** (declaration statement),比如进行变量绑定的`let`语句。
18+
2. **表达式语句** (expression statement),它通过在末尾加上分号`;`来将表达式变成语句,
19+
丢弃该表达式的值,一律返回元类型`()`
20+
21+
表示式总是返回一个值,但是语句不返回值或者返回`()`,所以以下代码会报错:
22+
23+
```rust
24+
let y = (let x = 5);
25+
26+
let z: i32 = if x == 5 { 10; } else { 15; };
27+
```
28+
29+
值得注意的是,在Rust中赋值 (如`x = 5`) 也是一个表达式,返回元类型值`()`
30+
31+
## For
32+
33+
Rust中的`for`循环与C语言的风格非常不同,抽象结构如下:
34+
35+
```rust
36+
for var in expression {
37+
code
38+
}
39+
```
40+
其中`expression`是一个迭代器 (iterator),具体的例子为`0..10` (不包含最后一个值),
41+
或者`[0, 1, 2].iter()`
42+
43+
## While
44+
45+
Rust中的`while`循环与C语言中的类似。对于无限循环,Rust有一个专用的关键字`loop`
46+
如果需要提前退出循环,可以使用关键字`break`或者`continue`
47+
还允许在循环的开头设定标签 (同样适用于`for`循环):
48+
49+
```rust
50+
'outer: loop {
51+
println!("Entered the outer loop");
52+
53+
'inner: loop {
54+
println!("Entered the inner loop");
55+
break 'outer;
56+
}
57+
58+
println!("This point will never be reached");
59+
}
60+
61+
println!("Exited the outer loop");
62+
```
63+
64+
## Match
65+
66+
Rust中的`match`表达式非常强大,首先看一个例子:
67+
68+
```rust
69+
let day = 5;
70+
71+
match day {
72+
0 | 6 => println!("weekend"),
73+
1 ... 5 => println!("weekday"),
74+
_ => println!("invalid"),
75+
}
76+
```
77+
其中`|`用于匹配多个值,`...`匹配一个范围 (包含最后一个值),并且`_`在这里是必须的,
78+
因为`match`强制进行穷尽性检查 (exhaustiveness checking),必须覆盖所有的可能值。
79+
如果需要得到`|`或者`...`匹配到的值,可以使用`@`绑定变量:
80+
81+
```rust
82+
let x = 1;
83+
84+
match x {
85+
e @ 1 ... 5 => println!("got a range element {}", e),
86+
_ => println!("anything"),
87+
}
88+
```
89+
90+
使用`ref`关键字来得到一个引用:
91+
92+
```rust
93+
let x = 5;
94+
let mut y = 5;
95+
96+
match x {
97+
// the `r` inside the match has the type `&i32`
98+
ref r => println!("Got a reference to {}", r),
99+
}
100+
101+
match y {
102+
// the `mr` inside the match has the type `&i32` and is mutable
103+
ref mut mr => println!("Got a mutable reference to {}", mr),
104+
}
105+
```
106+
107+
再看一个使用`match`表达式来解构元组的例子:
108+
109+
```rust
110+
let pair = (0, -2);
111+
112+
match pair {
113+
(0, y) => println!("x is `0` and `y` is `{:?}`", y),
114+
(x, 0) => println!("`x` is `{:?}` and y is `0`", x),
115+
_ => println!("It doesn't matter what they are"),
116+
}
117+
```
118+
119+
`match`的这种解构同样适用于结构体或者枚举。如果有必要,
120+
还可以使用`..`来忽略域或者数据:
121+
122+
```rust
123+
struct Point {
124+
x: i32,
125+
y: i32,
126+
}
127+
128+
let origin = Point { x: 0, y: 0 };
129+
130+
match origin {
131+
Point { x, .. } => println!("x is {}", x),
132+
}
133+
134+
enum OptionalInt {
135+
Value(i32),
136+
Missing,
137+
}
138+
139+
let x = OptionalInt::Value(5);
140+
141+
match x {
142+
OptionalInt::Value(i) if i > 5 => println!("Got an int bigger than five!"),
143+
OptionalInt::Value(..) => println!("Got an int!"),
144+
OptionalInt::Missing => println!("No such luck."),
145+
}
146+
```
147+
148+
此外,Rust还引入了`if let``while let`进行模式匹配:
149+
150+
```rust
151+
let number = Some(7);
152+
let mut optional = Some(0);
153+
154+
// If `let` destructures `number` into `Some(i)`, evaluate the block.
155+
if let Some(i) = number {
156+
println!("Matched {:?}!", i);
157+
} else {
158+
println!("Didn't match a number!");
159+
}
160+
161+
// While `let` destructures `optional` into `Some(i)`, evaluate the block.
162+
while let Some(i) = optional {
163+
if i > 9 {
164+
println!("Greater than 9, quit!");
165+
optional = None;
166+
} else {
167+
println!("`i` is `{:?}`. Try again.", i);
168+
optional = Some(i + 1);
169+
}
170+
}
171+
```
172+

0 commit comments

Comments
 (0)