Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
梦境迷离
Cs Summary Reflection
提交
2f0f026d
C
Cs Summary Reflection
项目概览
梦境迷离
/
Cs Summary Reflection
12 个月 前同步成功
通知
4
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
C
Cs Summary Reflection
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
2f0f026d
编写于
1月 19, 2020
作者:
梦
梦境迷离
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
add rust
上级
15a4e74b
变更
16
展开全部
隐藏空白更改
内联
并排
Showing
16 changed file
with
1426 addition
and
812 deletion
+1426
-812
rust-exercise/Cargo.toml
rust-exercise/Cargo.toml
+3
-0
rust-exercise/src/collection_function.rs
rust-exercise/src/collection_function.rs
+167
-0
rust-exercise/src/control_function.rs
rust-exercise/src/control_function.rs
+86
-0
rust-exercise/src/enum_data_type.rs
rust-exercise/src/enum_data_type.rs
+91
-0
rust-exercise/src/example_guessing_game.rs
rust-exercise/src/example_guessing_game.rs
+51
-0
rust-exercise/src/generic_traits_lifetimes.rs
rust-exercise/src/generic_traits_lifetimes.rs
+306
-0
rust-exercise/src/lib.rs
rust-exercise/src/lib.rs
+1
-1
rust-exercise/src/main.rs
rust-exercise/src/main.rs
+44
-811
rust-exercise/src/match_syntax.rs
rust-exercise/src/match_syntax.rs
+117
-0
rust-exercise/src/method_syntax.rs
rust-exercise/src/method_syntax.rs
+64
-0
rust-exercise/src/other_function.rs
rust-exercise/src/other_function.rs
+70
-0
rust-exercise/src/panic_function.rs
rust-exercise/src/panic_function.rs
+94
-0
rust-exercise/src/point_function.rs
rust-exercise/src/point_function.rs
+48
-0
rust-exercise/src/simple_array_data_type.rs
rust-exercise/src/simple_array_data_type.rs
+91
-0
rust-exercise/src/struct_data_type.rs
rust-exercise/src/struct_data_type.rs
+109
-0
rust-exercise/src/variables_function.rs
rust-exercise/src/variables_function.rs
+84
-0
未找到文件。
rust-exercise/Cargo.toml
浏览文件 @
2f0f026d
...
...
@@ -10,3 +10,6 @@ edition = "2018"
#新增随机数支持依赖,该数字0.5.5实际上是的简写^0.5.5,表示“具有与0.5.5版兼容的公共API的任何版本。”
rand
=
"0.5.5"
[profile.release]
panic
=
'abort'
#发布模式下因恐慌(panic,不可恢复的错误,类似Java的error)而中止,通过将RUST_BACKTRACE环境变量设置为除0以外的任何值来获得错误的确切原因的回溯
rust-exercise/src/collection_function.rs
0 → 100644
浏览文件 @
2f0f026d
use
std
::
string
::
ToString
;
///https://doc.rust-lang.org/stable/nomicon/vec.html.
///集合
pub
fn
collection_function
()
{
let
mut
v
:
Vec
<
i32
>
=
Vec
::
new
();
//Vec类似ArrayList,称为向量?
v
.push
(
12
);
//想要修改必须定义为mut可变的
println!
(
"{:#?}"
,
v
);
let
v
=
vec!
[
1
,
2
,
3
];
println!
(
"{:#?}"
,
v
);
let
v
=
vec!
[
1
,
2
,
3
,
4
,
5
];
let
third
=
&
v
[
2
];
//获取元素
println!
(
"The third element is {}"
,
third
);
match
v
.get
(
2
)
{
Some
(
third
)
=>
println!
(
"The third element is {}"
,
third
),
None
=>
println!
(
"There is no third element."
),
}
//let does_not_exist = &v[100];//恐慌,编译时直接退出程序
///当将get方法传递给向量之外的索引时,它将返回None且不会出现惊慌。如果在正常情况下偶尔访问超出向量范围的元素,则可以使用此方法。
///您的代码将需要具有处理Some(&element)或None的逻辑,
let
does_not_exist
=
v
.get
(
100
);
///当程序具有有效的引用时,借位检查器将执行所有权和借用规则
let
mut
v
=
vec!
[
1
,
2
,
3
,
4
,
5
];
let
first
=
v
[
0
];
//使用引用&v[0]将会报错
v
.push
(
6
);
//尝试保留第一个元素的引用的同时向向量添加元素将会出现编译错误,此时引用可能改变
println!
(
"The first element is: {}"
,
first
);
///遍历向量集合
let
v
=
vec!
[
100
,
32
,
57
];
for
i
in
&
v
{
println!
(
"{}"
,
i
);
//直接打印 i,而不需要使用c语言中的*i,省略了*
}
let
mut
v
=
vec!
[
100
,
32
,
57
];
for
i
in
&
mut
v
{
*
i
+=
50
;
//对可变的向量进行操作,让每个元素都增加50
println!
(
"{}"
,
i
)
}
///定义一个枚举以将不同类型的值存储在一个向量中
enum
SpreadsheetCell
{
Int
(
i32
),
Float
(
f64
),
Text
(
String
),
}
///Rust需要知道在编译时向量中将包含哪些类型,因此Rust确切知道要存储每个元素需要多少内存。第二个优点是,我们可以明确说明此向量允许哪些类型。
///如果Rust允许向量保留任何类型,则一个或多个类型可能会导致对向量元素执行的操作出错。使用枚举加上match表达式意味着Rust将确保在编译时处理所有可能的情况
///在编写程序时,如果您不知道该程序在运行时会存储到向量中的所有可能类型,则枚举技术将不起作用。相反,您可以使用trait对象
let
row
=
vec!
[
SpreadsheetCell
::
Int
(
3
),
SpreadsheetCell
::
Text
(
String
::
from
(
"blue"
)),
SpreadsheetCell
::
Float
(
10.12
),
];
///使用字符串存储UTF-8编码文本
///Rust在核心语言中只有一种字符串类型,即字符串切片str,通常以借用的形式&str获取。
///字符串类型是Rust的标准库提供的,而不是编码为核心语言的字符串类型,它是一种可增长,可变,拥有的,以UTF-8编码的字符串类型。
///当rust开发者在Rust中引用“字符串”时,它们通常是指String和字符串切片&str类型,而不仅仅是这些类型之一。
///Rust的标准库还包括许多其他字符串类型,例如OsString,OsStr,CString和CStr。Library crates可以提供更多用于存储字符串数据的选项。
///看看这些名称如何全部以String或Str结尾?它们是指拥有和借用的变体,就像您之前看到的String和str类型一样。
///例如,这些字符串类型可以用不同的编码存储文本,或以不同的方式在内存中表示。
let
data
=
"initial contents"
;
let
s
=
data
.to_string
();
println!
(
"{}"
,
s
);
let
s
=
"initial contents"
.to_string
();
println!
(
"{}"
,
s
);
let
s
=
String
::
from
(
"initial contents"
);
//从字符串文字(字符串常量 切片 &str类型)创建字符串(对象/String类型)
println!
(
"{}"
,
s
);
//其他编码的文字
let
hello
=
String
::
from
(
"السلام عليكم"
);
let
hello
=
String
::
from
(
"Dobrý den"
);
let
hello
=
String
::
from
(
"Hello"
);
let
hello
=
String
::
from
(
"שָׁלוֹם"
);
let
hello
=
String
::
from
(
"नमस्ते"
);
let
hello
=
String
::
from
(
"こんにちは"
);
let
hello
=
String
::
from
(
"안녕하세요"
);
let
hello
=
String
::
from
(
"你好"
);
let
hello
=
String
::
from
(
"Olá"
);
let
hello
=
String
::
from
(
"Здравствуйте"
);
let
hello
=
String
::
from
(
"Hola"
);
///修改字符串,使用push_str方法将字符串切片附加到String
let
mut
s
=
String
::
from
(
"foo"
);
s
.push_str
(
"bar"
);
let
mut
s1
=
String
::
from
(
"foo"
);
let
s2
=
"bar"
;
s1
.push_str
(
s2
);
println!
(
"s2 is {}"
,
s2
);
//s2被加到s1之后,再次使用s2
let
mut
s
=
String
::
from
(
"lo"
);
s
.push
(
'l'
);
//使用push向字符串值添加一个字符
///合并字符串
let
s1
=
String
::
from
(
"Hello, "
);
let
s2
=
String
::
from
(
"world!"
);
let
s3
=
s1
+
&
s2
;
//s1被移动,之后无法再次使用
//+ 方法 使用add方法 fn add(self, s: &str) -> String {
//所以+组合字符串第二个参数必须是 &str的,但是这是因为编译器将&String转化为&str了。
let
s1
=
String
::
from
(
"tic"
);
let
s2
=
String
::
from
(
"tac"
);
let
s3
=
String
::
from
(
"toe"
);
///如果需要连接多个字符串,则+运算符的行为会变得笨拙:
let
s
=
s1
+
"-"
+
&
s2
+
"-"
+
&
s3
;
///对于更复杂的字符串组合,我们可以使用format! 宏
let
s1
=
String
::
from
(
"tic"
);
let
s2
=
String
::
from
(
"tac"
);
let
s3
=
String
::
from
(
"toe"
);
let
s
=
format!
(
"{}-{}-{}"
,
s1
,
s2
,
s3
);
println!
(
"{}"
,
s
);
///Rust字符串不支持索引
//let h = s1[0]; //编译报错
///与字符串内部的实现相关,字符串是Vec<u8>的包装
let
len
=
String
::
from
(
"Hola"
)
.len
();
println!
(
"{}"
,
len
);
let
len
=
String
::
from
(
"Здравствуйте"
)
.len
();
println!
(
"{}"
,
len
);
///当问到字符串有多长时,您可能会说12。但是,Rust的答案是24:这就是在UTF-8中编码“Здравствуйте”所需的字节数,因为该字符串中的每个Unicode标量值都占用2个字节的存储空间。
///因此,字符串字节的索引并不总是与有效的Unicode标量值相关。为了演示,请考虑以下无效的Rust代码:
let
hello
=
"Здравствуйте"
;
//let answer = &hello[0];//编译报错
///Rust不允许我们索引到String中以获取字符的最后一个原因是索引操作总是需要恒定的时间(O(1))。
///但是用String不能保证性能,因为Rust必须从头到尾遍历所有内容以确定有多少个有效字符。
///有效的Unicode标量值可能由1个以上的字节组成,从rust字符串中获取字素簇很复杂,标准库并未提供此功能
for
c
in
"नमस्ते"
.chars
()
{
println!
(
"{}"
,
c
);
//न म स ् त े ,一个字符由2个char组成
}
for
b
in
"नमस्ते"
.bytes
()
{
println!
(
"{}"
,
b
);
//返回字节,很多个
}
///hash map
use
std
::
collections
::
HashMap
;
let
mut
scores
=
HashMap
::
new
();
scores
.insert
(
String
::
from
(
"Blue"
),
10
);
scores
.insert
(
String
::
from
(
"Yellow"
),
50
);
//从teams和initial_scores中创建map
let
teams
=
vec!
[
String
::
from
(
"Blue"
),
String
::
from
(
"Yellow"
)];
let
initial_scores
=
vec!
[
10
,
50
];
let
scores
:
HashMap
<
_
,
_
>
=
teams
.iter
()
.zip
(
initial_scores
.iter
())
.collect
();
///所有权
let
field_name
=
String
::
from
(
"Favorite color"
);
let
field_value
=
String
::
from
(
"Blue"
);
let
mut
map
=
HashMap
::
new
();
map
.insert
(
field_name
,
field_value
);
//此时field_name和field_value无效,已经被移动到map中
///获取key对应的value
let
team_name
=
String
::
from
(
"Blue"
);
let
score
=
scores
.get
(
&
team_name
);
///编译map
for
(
key
,
value
)
in
&
scores
{
println!
(
"{}: {}"
,
key
,
value
);
}
///更新map
//insert 覆盖旧值,scores.entry(String::from("Yellow")).or_insert(50);key不存在时插入
//根据旧值更新值
let
text
=
"hello world wonderful world"
;
let
mut
map
=
HashMap
::
new
();
for
word
in
text
.split_whitespace
()
{
let
count
=
map
.entry
(
word
)
.or_insert
(
0
);
*
count
+=
1
;
}
println!
(
"{:?}"
,
map
);
}
//v超出范围并在此处释放
rust-exercise/src/control_function.rs
0 → 100644
浏览文件 @
2f0f026d
///控制流
pub
fn
control_function
()
{
let
number
=
3
;
//表达式结果必须是bool类型,不像c会自动将非bool转化为bool,if上不能使用文档注释
if
number
<
5
{
println!
(
"condition was true"
);
}
else
{
println!
(
"condition was false"
);
}
///处理多个if
let
number
=
6
;
//阴影,遮盖了前面的number
if
number
%
4
==
0
{
println!
(
"number is divisible by 4"
);
}
else
if
number
%
3
==
0
{
println!
(
"number is divisible by 3"
);
}
else
if
number
%
2
==
0
{
println!
(
"number is divisible by 2"
);
}
else
{
println!
(
"number is not divisible by 4, 3, or 2"
);
}
///与Scala一样,可以将if表达式的结果赋值给变量(这里的变量一般是指不可变的变量,虽然绕口,但是确实是事实)
let
condition
=
true
;
///从每个分支取得的if的返回值必须是同一类型,否则编译报错
let
number
=
if
condition
{
5
}
else
{
6
};
println!
(
"The value of number is: {}"
,
number
);
///循环
loop
{
println!
(
"again!"
);
break
;
//这个分号可省
}
///从循环中返回值
let
mut
counter
=
0
;
//循环赋值给变量
let
result
=
loop
{
counter
+=
1
;
if
counter
==
10
{
break
counter
*
2
;
};
//这个分号可省
};
///分号的使用还不清晰明确,后面再看
///暂时理解为,赋值给变量的代码块需要使用分号短句,不赋值可以不用分号,而表达式本身就是直接返回,使用分号反而不行。(return显示指定返回值)
println!
(
"The result is {}"
,
result
);
///while循环
let
mut
number
=
3
;
///使用while可以减少大量的if else break
while
number
!=
0
{
println!
(
"{}!"
,
number
);
number
-=
1
;
};
//这个分号可以省略
println!
(
"LIFTOFF!!!"
);
///while变量数组
let
a
=
[
10
,
20
,
30
,
40
,
50
];
let
mut
index
=
0
;
while
index
<
5
{
println!
(
"the value is: {}"
,
a
[
index
]);
index
+=
1
;
}
///使用for循环更加简单
///rust常用for,因为rust不会有迭代器失效的问题
let
a
=
[
10
,
20
,
30
,
40
,
50
];
for
element
in
a
.iter
()
{
println!
(
"the value is: {}"
,
element
);
}
///使用倒数
for
number
in
(
1
..
4
)
.rev
()
{
//输出3!2!1!LIFTOFF!!! print是没有换行的,与其他语言一致
print!
(
"{}!"
,
number
);
}
println!
(
"LIFTOFF!!!"
);
}
\ No newline at end of file
rust-exercise/src/enum_data_type.rs
0 → 100644
浏览文件 @
2f0f026d
///枚举类型
pub
fn
enum_data_type
()
{
///定义枚举类型
enum
IpAddrKind
{
V4
,
V6
,
}
let
four
=
IpAddrKind
::
V4
;
let
six
=
IpAddrKind
::
V6
;
fn
route
(
ip_kind
:
IpAddrKind
)
{}
///两个值IpAddrKind::V4和IpAddrKind::V6都具有相同的类型: IpAddrKind
route
(
IpAddrKind
::
V4
);
route
(
IpAddrKind
::
V6
);
struct
IpAddr
{
//在结构体中使用枚举
kind
:
IpAddrKind
,
address
:
String
,
}
let
home
=
IpAddr
{
kind
:
IpAddrKind
::
V4
,
address
:
String
::
from
(
"127.0.0.1"
),
};
let
loopback
=
IpAddr
{
kind
:
IpAddrKind
::
V6
,
address
:
String
::
from
(
"::1"
),
};
///数值直接放入每个枚举变量中,而不是需要使用结构体 struct IpAddr
enum
IpAddr2
{
V4
(
String
),
V6
(
String
),
}
let
home
=
IpAddr2
::
V4
(
String
::
from
(
"127.0.0.1"
));
let
loopback
=
IpAddr2
::
V6
(
String
::
from
(
"::1"
));
///将枚举数值定义为不同类型,此时struct IpAddr无法实现
enum
IpAddr3
{
V4
(
u8
,
u8
,
u8
,
u8
),
V6
(
String
),
}
let
home
=
IpAddr3
::
V4
(
127
,
0
,
0
,
1
);
let
loopback
=
IpAddr3
::
V6
(
String
::
from
(
"::1"
));
///使用枚举
enum
Message
{
Quit
,
Move
{
x
:
i32
,
y
:
i32
},
Write
(
String
),
ChangeColor
(
i32
,
i32
,
i32
),
}
///使用结构体
struct
QuitMessage
;
// 单位结构
struct
MoveMessage
{
x
:
i32
,
y
:
i32
,
}
struct
WriteMessage
(
String
);
// 元祖结构
struct
ChangeColorMessage
(
i32
,
i32
,
i32
);
// 元祖结构
///定义一个impl即可对所有枚举值生效,他们都能调用call
impl
Message
{
fn
call
(
&
self
)
{
// do something
}
}
let
m
=
Message
::
Write
(
String
::
from
(
"hello"
));
m
.call
();
///Option类型
let
some_number
=
Some
(
5
);
let
some_string
=
Some
(
"a string"
);
//为None时需要指定类型,否则无法推断出类型
let
absent_number
:
Option
<
i32
>
=
None
;
let
x
:
i8
=
5
;
let
y
:
Option
<
i8
>
=
Some
(
5
);
//Option<i8> 与 i8 是不同的类型 <>是泛型,Option<T>表示任意的类型都可以放进Option
//let sum = x + y;
}
rust-exercise/src/example_guessing_game.rs
0 → 100644
浏览文件 @
2f0f026d
use
std
::
cmp
::
Ordering
;
use
std
::
io
;
use
rand
::
Rng
;
///简单的猜数字
pub
fn
example_guessing_game
()
{
println!
(
"Guess the number!"
);
///thread_rng一个在当前执行线程本地且由操作系统播种的随机数生成器
let
secret_number
=
rand
::
thread_rng
()
.gen_range
(
1
,
101
);
//println!("The secret number is: {}", secret_number);
loop
{
println!
(
"Please input your guess."
);
//变量默认是不可变的。使用mut表示变量是可变的,定义成let foo = 5; 则是不可变。
let
mut
guess
=
String
::
new
();
//关联函数,在类型上实现。一些语言称为静态方法。该函数创建了一个空串
//没有使用use,则这里需要写成 std::io::stdin
//&表示该参数是一个引用,Rust的主要优势之一是使用引用的安全性和便捷性
//&使您代码的多个部分可以访问同一条数据,而无需将该数据多次复制到内存中
io
::
stdin
()
.read_line
(
&
mut
guess
)
.expect
(
"Failed to read line"
);
//无法比较数值与字符串需要转化为数值,Rust默认为i32
//Rust允许我们用新的值遮盖以前的值guess。此功能通常用于要将值从一种类型转换为另一种类型的情况。
//阴影使我们可以重用guess变量名,而不是强迫我们创建两个唯一变量,例如guess_str和guess。
//前面的guess是可变的,这个是不可变的。
//let guess: u32 = guess.trim().parse().expect("Please type a number!");//类型不明确,必须指定具体类型
//println!是宏
println!
(
"You guessed: {}"
,
guess
);
let
guess
:
u32
=
match
guess
.trim
()
.parse
()
{
Ok
(
num
)
=>
num
,
//遇到无效输入直接跳过
Err
(
_
)
=>
continue
,
};
println!
(
"Please input your guess."
);
match
guess
.cmp
(
&
secret_number
)
{
Ordering
::
Less
=>
println!
(
"Too small!"
),
Ordering
::
Greater
=>
println!
(
"Too big!"
),
Ordering
::
Equal
=>
{
println!
(
"You win!"
);
//猜到正确数字后退出循环
break
;
}
}
}
}
\ No newline at end of file
rust-exercise/src/generic_traits_lifetimes.rs
0 → 100644
浏览文件 @
2f0f026d
use
std
::
fmt
::{
Debug
,
Display
};
///通用类型,特征和寿命
pub
fn
largest_function
()
{
//在数字列表中查找最大数字的代码
let
number_list
=
vec!
[
34
,
50
,
25
,
100
,
65
];
let
mut
largest
=
number_list
[
0
];
for
number
in
number_list
{
if
number
>
largest
{
largest
=
number
;
}
}
println!
(
"The largest number is {}"
,
largest
);
///使用通用函数代码
let
number_list
=
vec!
[
34
,
50
,
25
,
100
,
65
];
let
result
=
largest1
(
&
number_list
);
println!
(
"The largest number is {}"
,
result
);
let
number_list
=
vec!
[
102
,
34
,
6000
,
89
,
54
,
2
,
43
,
8
];
let
result
=
largest1
(
&
number_list
);
println!
(
"The largest number is {}"
,
result
);
///使用更加通用的函数代码(泛型)
let
number_list
=
vec!
[
34
,
50
,
25
,
100
,
65
];
let
result
=
largest2
(
&
number_list
);
println!
(
"The largest number is {}"
,
result
);
let
char_list
=
vec!
[
'y'
,
'm'
,
'a'
,
'q'
];
let
result
=
largest2
(
&
char_list
);
println!
(
"The largest char is {}"
,
result
);
}
///提取通用逻辑(此时类型都是i32,还可以进一步抽象为通用)
fn
largest1
(
list
:
&
[
i32
])
->
i32
{
let
mut
largest
=
list
[
0
];
for
&
item
in
list
.iter
()
{
if
item
>
largest
{
largest
=
item
;
}
}
largest
}
///使用泛型并且限定泛型需要特质
fn
largest2
<
T
:
PartialOrd
+
Copy
>
(
list
:
&
[
T
])
->
T
{
let
mut
largest
=
list
[
0
];
for
&
item
in
list
.iter
()
{
if
item
>
largest
{
largest
=
item
;
}
}
largest
}
///在结构中使用泛型
fn
struct_generic
()
{
struct
Point
<
T
>
{
x
:
T
,
//由此可见,x/y它们具有相同的通用数据类型T
y
:
T
,
}
let
integer
=
Point
{
x
:
5
,
y
:
10
};
let
float
=
Point
{
x
:
1.0
,
y
:
4.0
};
struct
Point2
<
T
,
U
>
{
x
:
T
,
//x/y类型不同
y
:
U
,
}
let
both_integer
=
Point2
{
x
:
5
,
y
:
10
};
let
both_float
=
Point2
{
x
:
1.0
,
y
:
4.0
};
let
integer_and_float
=
Point2
{
x
:
5
,
y
:
4.0
};
}
///在枚举和方法中定义
pub
fn
enum_generic
()
{
enum
Option
<
T
>
{
Some
(
T
),
None
,
}
struct
Point
<
T
>
{
x
:
T
,
y
:
T
,
}
impl
<
T
>
Point
<
T
>
{
fn
x
(
&
self
)
->
&
T
{
&
self
.x
}
}
let
p
=
Point
{
x
:
5
,
y
:
10
};
println!
(
"p.x = {}"
,
p
.x
());
///这意味着后面不能再实现任何其他类型impl
impl
Point
<
f32
>
{
fn
distance_from_origin
(
&
self
)
->
f32
{
(
self
.x
.powi
(
2
)
+
self
.y
.powi
(
2
))
.sqrt
()
}
}
struct
Point2
<
T
,
U
>
{
x
:
T
,
y
:
U
,
}
///多种泛型,方法自带了V W
impl
<
T
,
U
>
Point2
<
T
,
U
>
{
//V W仅与方法相关,T U是该结构的通用泛型
fn
mixup
<
V
,
W
>
(
self
,
other
:
Point2
<
V
,
W
>
)
->
Point2
<
T
,
W
>
{
Point2
{
x
:
self
.x
,
y
:
other
.y
,
}
}
}
let
p1
=
Point2
{
x
:
5
,
y
:
10.4
};
let
p2
=
Point2
{
x
:
"Hello"
,
y
:
'c'
};
let
p3
=
p1
.mixup
(
p2
);
println!
(
"p3.x = {}, p3.y = {}"
,
p3
.x
,
p3
.y
);
//Rust通过在编译时对使用泛型的代码进行单态化来实现这一点。单色化是通过填充编译时使用的具体类型,将通用代码转换为特定代码的过程。
//所以rust泛型高效
}
///特性:定义共同的行为
pub
fn
trait_function
()
{
///定义一个特质
pub
trait
Summary
{
fn
summarize
(
&
self
)
->
String
;
}
pub
struct
NewsArticle
{
pub
headline
:
String
,
pub
location
:
String
,
pub
author
:
String
,
pub
content
:
String
,
}
///在NewsArticle类型上,实现特质Summary
impl
Summary
for
NewsArticle
{
fn
summarize
(
&
self
)
->
String
{
format!
(
"{}, by {} ({})"
,
self
.headline
,
self
.author
,
self
.location
)
}
}
pub
struct
Tweet
{
pub
username
:
String
,
pub
content
:
String
,
pub
reply
:
bool
,
pub
retweet
:
bool
,
}
///在Tweet类型上,实现特质Summary
impl
Summary
for
Tweet
{
fn
summarize
(
&
self
)
->
String
{
format!
(
"{}: {}"
,
self
.username
,
self
.content
)
}
}
///使用特质Summary的summarize方法
let
tweet
=
Tweet
{
username
:
String
::
from
(
"horse_ebooks"
),
content
:
String
::
from
(
"of course, as you probably already know, people"
),
reply
:
false
,
retweet
:
false
,
};
println!
(
"1 new tweet: {}"
,
tweet
.summarize
());
//只有特征或类型在板条箱中是本地的时,我们才能对类型实现特征
//此规则可确保其他人的代码不会破坏您的代码,反之亦然。
//孤立规则(滑稽,翻译的):如果没有该规则,则两个包装箱可能会针对同一类型实现相同的特征,而Rust不会知道要使用哪种实现
///使用特质的默认使用:impl Summary for NewsArticle {}。
///使用特质作为参数
pub
fn
notify
(
item
:
impl
Summary
)
{
println!
(
"Breaking news! {}"
,
item
.summarize
());
}
///特质绑定语法,与上面的效果类似但不等价
pub
fn
notify2
<
T
:
Summary
>
(
item
:
T
)
{
println!
(
"Breaking news! {}"
,
item
.summarize
());
}
///使用impl Summary作为参数会更加方便,此时只要求item1和item2参数实现了Summary,而不要求他们类型完全一致
pub
fn
notify3
(
item1
:
impl
Summary
,
item2
:
impl
Summary
)
{
println!
(
"Breaking news! {}"
,
item1
.summarize
());
}
///需要强制让item1和item2的类型是一致的,则必须要使用特质绑定
pub
fn
notify4
<
T
:
Summary
>
(
item1
:
T
,
item2
:
T
)
{
println!
(
"Breaking news! {}"
,
item1
.summarize
());
}
///使用+,限制参数必须同时实现多个特质
pub
fn
notify5
(
item
:
impl
Summary
+
Display
)
{
println!
(
"Breaking news! {}"
,
item
.summarize
());
}
///使用特质绑定,限定T必须实现了两个特质
pub
fn
notify6
<
T
:
Summary
+
Display
>
(
item
:
T
)
{
println!
(
"Breaking news! {}"
,
item
.summarize
());
}
///这样写太麻烦
fn
some_function
<
T
:
Display
+
Clone
,
U
:
Clone
+
Debug
>
(
t
:
T
,
u
:
U
)
->
i32
{
1
}
//简化
fn
some_function2
<
T
,
U
>
(
t
:
T
,
u
:
U
)
->
i32
where
T
:
Display
+
Clone
,
U
:
Clone
+
Debug
{
1
}
///返回实现特征的类型
fn
returns_summarizable
()
->
impl
Summary
{
Tweet
{
username
:
String
::
from
(
"horse_ebooks"
),
content
:
String
::
from
(
"of course, as you probably already know, people"
),
reply
:
false
,
retweet
:
false
,
}
}
//下面是无效的,编译不过
//由于在编译器中实现impl Trait语法方面的限制,因此不允许返回NewsArticle或Tweet
// fn returns_summarizable2(switch: bool) -> impl Summary {
// if switch {
// NewsArticle {
// headline: String::from("Penguins win the Stanley Cup Championship!"),
// location: String::from("Pittsburgh, PA, USA"),
// author: String::from("Iceburgh"),
// content: String::from("The Pittsburgh Penguins once again are the best
// hockey team in the NHL."),
// }
// } else {
// Tweet {
// username: String::from("horse_ebooks"),
// content: String::from("of course, as you probably already know, people"),
// reply: false,
// retweet: false,
// }
// }
// }
struct
Pair
<
T
>
{
x
:
T
,
y
:
T
,
}
impl
<
T
>
Pair
<
T
>
{
fn
new
(
x
:
T
,
y
:
T
)
->
Self
{
Self
{
x
,
y
,
}
}
}
///始终实现new函数,但是Pair<T>仅在内部类型T实现了实现比较的PartialOrd特质和实现打印的Display特质的情况下,才实现cmp_display方法。
///根据特质范围有条件地在泛型类型上实现方法
impl
<
T
:
Display
+
PartialOrd
>
Pair
<
T
>
{
fn
cmp_display
(
&
self
)
{
if
self
.x
>=
self
.y
{
println!
(
"The largest member is x = {}"
,
self
.x
);
}
else
{
println!
(
"The largest member is y = {}"
,
self
.y
);
}
}
}
}
///生命周期
fn
lifetimes_function
()
{
//使用生命周期验证引用
//在大多数情况下,生存期是隐式和推断的,就像在大多数情况下一样,推断类型。
//当可能有多个类型时,必须注释类型。以类似的方式,当引用的生存期可以通过几种不同方式关联时,我们必须注释生存期。
//Rust要求我们使用通用生命周期参数注释关系,以确保在运行时使用的实际引用绝对有效。
//生命周期的主要目的是防止引用悬而未决,从而导致程序引用的数据不是其要引用的数据。
// {
// r和x的生命周期注释,分别命名为'a和'b
// let r; // ---------+-- 'a
// |
// { // |
// let x = 5; // -+-- 'b |
// r = &x; // | |
// } // -+ |
// |
// println!("r: {}", r); // |
// } // ----------+
///正确代码
{
let
x
=
5
;
// ----------+-- 'b
// |
let
r
=
&
x
;
// --+-- 'a |
// | |
println!
(
"r: {}"
,
r
);
// | |
// --+ |
}
// ----------+
///函数的通用生命周期
///过于复杂,建议有时间再研究:https://doc.rust-lang.org/book/ch10-03-lifetime-syntax.html
// &i32 // 一个引用
// &'a i32 // 具有明确生命周期的引用
// &'a mut i32 // 具有显式寿命的可变引用
///指定签名中的所有引用必须具有相同的生存期 'a
fn
longest
<
'a
>
(
x
:
&
'a
str
,
y
:
&
'a
str
)
->
&
'a
str
{
if
x
.len
()
>
y
.len
()
{
x
}
else
{
y
}
}
}
rust-exercise/src/lib.rs
浏览文件 @
2f0f026d
...
...
@@ -75,7 +75,7 @@ mod back_of_house {
//mod front_of_house;//在mod front_of_house之后使用分号(而不是使用块)会告诉Rust从另一个与模块同名的文件中加载模块的内容。
//重新导出,使名称可用于新范围内的任何代码 (因为我们将一个项目放入范围内,同时也使该项目可供其他人进入其范围)
//
pub use
重新导出,使名称可用于新范围内的任何代码 (因为我们将一个项目放入范围内,同时也使该项目可供其他人进入其范围)
//use std::collections::*; //导入所有内部的类型
pub
fn
eat_at_restaurant2
()
{
...
...
rust-exercise/src/main.rs
浏览文件 @
2f0f026d
此差异已折叠。
点击以展开。
rust-exercise/src/match_syntax.rs
0 → 100644
浏览文件 @
2f0f026d
///简洁的控制流语法
pub
fn
match_syntax2
()
{
let
some_u8_value
=
Some
(
0u8
);
match
some_u8_value
{
Some
(
3
)
=>
println!
(
"three"
),
_
=>
()
//这行是多余的样板代码
}
//使用if let 省略上面的样板代码
if
let
Some
(
3
)
=
some_u8_value
{
println!
(
"three"
);
}
#[derive(Debug)]
enum
UsState
{
Alabama
,
Alaska
,
}
enum
Coin
{
Penny
,
Nickel
,
Dime
,
Quarter
(
UsState
),
}
//使用if let简化代码
fn
value_in_cents
(
coin
:
Coin
)
->
u8
{
let
mut
count
=
0
;
if
let
Coin
::
Quarter
(
state
)
=
coin
{
println!
(
"State quarter from {:?}!"
,
state
);
}
else
{
count
+=
1
;
}
1
}
}
pub
fn
match_syntax
()
{
///枚举与match
enum
Coin
{
Penny
,
Nickel
,
Dime
,
Quarter
,
}
fn
value_in_cents
(
coin
:
Coin
)
->
u8
{
match
coin
{
Coin
::
Penny
=>
1
,
Coin
::
Nickel
=>
5
,
Coin
::
Dime
=>
10
,
Coin
::
Quarter
=>
25
,
}
}
fn
value_in_cents2
(
coin
:
Coin
)
->
u8
{
match
coin
{
Coin
::
Penny
=>
{
///代码多时需要使用花括号,并且最后一行返回值不加分号。大括号后面仍是逗号
println!
(
"Lucky penny!"
);
1
}
Coin
::
Nickel
=>
5
,
Coin
::
Dime
=>
10
,
Coin
::
Quarter
=>
25
,
}
}
///绑定到值的匹配
#[derive(Debug)]
enum
UsState
{
Alabama
,
Alaska
,
}
enum
Coin2
{
Penny
,
Nickel
,
Dime
,
Quarter
(
UsState
),
}
fn
value_in_cents3
(
coin
:
Coin2
)
->
u8
{
match
coin
{
Coin2
::
Penny
=>
1
,
Coin2
::
Nickel
=>
5
,
Coin2
::
Dime
=>
10
,
Coin2
::
Quarter
(
state
)
=>
{
println!
(
"State quarter from {:?}!"
,
state
);
25
}
}
}
///Option类型match
fn
plus_one
(
x
:
Option
<
i32
>
)
->
Option
<
i32
>
{
match
x
{
//这行代码多余,但是又不能省略,否则编译报错。
None
=>
None
,
Some
(
i
)
=>
Some
(
i
+
1
),
}
}
let
five
=
Some
(
5
);
let
six
=
plus_one
(
five
);
let
none
=
plus_one
(
None
);
///使用占位符,编译通过
let
some_u8_value
=
0u8
;
match
some_u8_value
{
1
=>
println!
(
"one"
),
3
=>
println!
(
"three"
),
5
=>
println!
(
"five"
),
7
=>
println!
(
"seven"
),
_
=>
()
}
}
rust-exercise/src/method_syntax.rs
0 → 100644
浏览文件 @
2f0f026d
///方法语法
pub
fn
method_syntax
()
{
///方法语法,方法与函数不同
#[derive(Debug)]
struct
Rectangle
{
width
:
u32
,
height
:
u32
,
}
///结构体的实现块,方法第一个参数必须是&self,不需要声明类型(impl与struct名称相同,能自动推断self类型,这也是能自动引用、取消引用的原因)
impl
Rectangle
{
//把2个方法放在多个impl实现也是可以的
fn
area
(
&
self
)
->
u32
{
self
.width
*
self
.height
}
//新增方法,有额外参数
fn
can_hold
(
&
self
,
other
:
&
Rectangle
)
->
bool
{
self
.width
>
other
.width
&&
self
.height
>
other
.height
}
//关联函数,没有self,类似其他语言的静态方法,但不是rust方法
fn
square
(
size
:
u32
)
->
Rectangle
{
Rectangle
{
width
:
size
,
height
:
size
}
}
}
let
rect1
=
Rectangle
{
width
:
30
,
height
:
50
};
///c/c++中如果object是一个指针, object->something() 与 (*object).something()等价
///Rust没有等效于->运算符;相反,Rust具有称为自动引用和取消引用的功能。调用方法是Rust少数具有这种行为的地方之一。
///工作原理如下:当您使用object.something()调用方法时,Rust会自动添加&,&mut或*,从而使对象与方法的签名匹配。换句话说,以下是相同的:
///p1.distance(&p2);
///(&p1).distance(&p2);
println!
(
"The area of the rectangle is {} square pixels."
,
rect1
.area
()
);
///方法参数
let
rect1
=
Rectangle
{
width
:
30
,
height
:
50
};
let
rect2
=
Rectangle
{
width
:
10
,
height
:
40
};
let
rect3
=
Rectangle
{
width
:
60
,
height
:
45
};
println!
(
"Can rect1 hold rect2? {}"
,
rect1
.can_hold
(
&
rect2
));
println!
(
"Can rect1 hold rect3? {}"
,
rect1
.can_hold
(
&
rect3
));
///impl块的另一个有用功能是允许我们在不以self为参数的impl块中定义函数。这些之所以称为关联函数,是因为它们与struct相关联。
///它们仍然是函数,而不是方法,因为它们没有可使用的结构实例
///关联函数通常用于将返回该结构的新实例的构造函数。例如,我们可以提供一个关联的函数,该函数将具有一个维度参数并将其用作宽度和高度,从而使创建矩形矩形变得更加容易,而不必两次指定相同的值:
let
sq
=
Rectangle
::
square
(
3
);
//类似调用静态方法
println!
(
"sq is {:#?}"
,
sq
);
///关联函数与结构体相关,但是没有self实例,他们仍是函数!!!
struct
Test
;
impl
Test
{
fn
test
()
->
String
{
String
::
from
(
"hello world"
)
}
}
let
test
=
Test
::
test
();
println!
(
"test is {:#?}"
,
test
);
}
\ No newline at end of file
rust-exercise/src/other_function.rs
0 → 100644
浏览文件 @
2f0f026d
use
rust_exercise
::
front_of_house
;
//引用外部的条板箱
pub
fn
crate_function
()
{
front_of_house
::
add_to_waitlist
()
}
//pub mod lib;
//
//fn crate_function_lib() {
// lib::eat_at_restaurant();
// lib::eat_at_restaurant2();
//}
pub
fn
return_function
()
{
let
s1
=
gives_ownership
();
// lets_ownership移动其返回值到s1中
let
s2
=
String
::
from
(
"hello"
);
// s2进入范围
let
s3
=
takes_and_gives_back
(
s2
);
// s2被移入takes_and_gives_back, takes_and_gives_back的返回值被移动到s3
println!
(
"{},{}"
,
s1
,
s3
);
fn
gives_ownership
()
->
String
{
// gives_ownership会其返回值移动到调用它的函数中
let
some_string
=
String
::
from
(
"hello"
);
// some_string进入范围
some_string
// 返回some_string字符串并移到调用函数
}
// take_and_gives_back将获取一个String并返回一个
fn
takes_and_gives_back
(
a_string
:
String
)
->
String
{
// a_string进入范围
a_string
// 返回a_string并移至调用函数
}
}
pub
fn
fib
(
n
:
i32
)
->
i32
{
if
n
==
0
{
0
}
else
if
n
==
1
{
1
}
else
{
fib
(
n
-
1
)
+
fib
(
n
-
2
)
}
}
pub
fn
fib_2
(
n
:
i32
)
->
i32
{
let
mut
a
=
0
;
let
mut
b
=
1
;
let
mut
c
=
0
;
if
n
==
0
||
n
==
1
{
n
}
else
{
for
number
in
2
..
(
n
+
1
)
{
c
=
a
+
b
;
a
=
b
;
b
=
c
;
}
c
}
}
//具有返回值的rust函数
pub
fn
five
()
->
i32
{
///这里同样,由于需要返回值为i32类型,增加了分号表示语句,没有返回值(实际是空括号),所以导致类型不一致,编译会报错
5
}
pub
fn
another_function
(
x
:
i32
)
{
//传参数的rust函数,与Scala一样,名称: 类型
println!
(
"The value of x is: {}"
,
x
);
}
\ No newline at end of file
rust-exercise/src/panic_function.rs
0 → 100644
浏览文件 @
2f0f026d
use
std
::{
fs
,
io
};
use
std
::
error
::
Error
;
use
std
::
fs
::
File
;
use
std
::
io
::{
ErrorKind
,
Read
};
///恐慌使用(error)
pub
fn
panic_function
()
{
let
f
=
File
::
open
(
"hello.txt"
);
let
f
=
match
f
{
Ok
(
file
)
=>
file
,
Err
(
error
)
=>
match
error
.kind
()
{
ErrorKind
::
NotFound
=>
match
File
::
create
(
"hello.txt"
)
{
Ok
(
fc
)
=>
fc
,
Err
(
e
)
=>
panic!
(
"Problem creating the file: {:?}"
,
e
),
//panic!打印错误信息,panic是不可恢复的错误
},
other_error
=>
panic!
(
"Problem opening the file: {:?}"
,
other_error
),
},
};
///使用闭包简化代码
//展开一个结果,得到一个[`Ok`]的内容。如果值是一个[`Err`],则用它的值调用'op'。
let
f
=
File
::
open
(
"hello.txt"
)
.unwrap_or_else
(|
error
|
{
if
error
.kind
()
==
ErrorKind
::
NotFound
{
File
::
create
(
"hello.txt"
)
.unwrap_or_else
(|
error
|
{
panic!
(
"Problem creating the file: {:?}"
,
error
);
})
}
else
{
panic!
(
"Problem opening the file: {:?}"
,
error
);
}
});
///如果Result值为Ok变体,unwrap则将在中返回该值Ok。如果Result是Err变体,unwrap将为panic!我们调用宏。
let
f
=
File
::
open
(
"hello.txt"
)
.unwrap
();
//一样,但是是自己传递错误信息给panic!宏
let
f
=
File
::
open
(
"hello.txt"
)
.expect
(
"Failed to open hello.txt"
);
///将错误返回到调用代码的函数
fn
read_username_from_file
()
->
Result
<
String
,
io
::
Error
>
{
let
f
=
File
::
open
(
"hello.txt"
);
let
mut
f
=
match
f
{
Ok
(
file
)
=>
file
,
Err
(
e
)
=>
return
Err
(
e
),
};
let
mut
s
=
String
::
new
();
match
f
.read_to_string
(
&
mut
s
)
{
Ok
(
_
)
=>
Ok
(
s
),
Err
(
e
)
=>
Err
(
e
),
}
}
///传播错误的捷径:?运算符
fn
read_username_from_file2
()
->
Result
<
String
,
io
::
Error
>
{
let
mut
f
=
File
::
open
(
"hello.txt"
)
?
;
//使用?运算符将错误返回到调用代码的函数,将错误自身转换为返回的错误类型。(From特质 from函数)
let
mut
s
=
String
::
new
();
f
.read_to_string
(
&
mut
s
)
?
;
Ok
(
s
)
}
fn
read_username_from_file3
()
->
Result
<
String
,
io
::
Error
>
{
let
mut
s
=
String
::
new
();
File
::
open
(
"hello.txt"
)
?
.read_to_string
(
&
mut
s
)
?
;
Ok
(
s
)
}
fn
read_username_from_file4
()
->
Result
<
String
,
io
::
Error
>
{
fs
::
read_to_string
(
"hello.txt"
)
}
//下面是在main方法中使用?的示例
// fn main() -> Result<(), Box<dyn Error>> {
// let f = File::open("hello.txt")?;
//
// Ok(())
// }
///创建一个新类型并将验证放入函数中以创建该类型的实例
//这样做的目的是,其他代码中不需要混入对该类型的检查
pub
struct
Guess
{
value
:
i32
,
}
impl
Guess
{
pub
fn
new
(
value
:
i32
)
->
Guess
{
if
value
<
1
||
value
>
100
{
panic!
(
"Guess value must be between 1 and 100, got {}."
,
value
);
}
Guess
{
value
}
}
pub
fn
value
(
&
self
)
->
i32
{
self
.value
}
}
}
\ No newline at end of file
rust-exercise/src/point_function.rs
0 → 100644
浏览文件 @
2f0f026d
///指针(引用)
pub
fn
empty_point_function
()
{
//let reference_to_nothing = dangle();
let
reference_to_nothing
=
no_dangle
();
fn
no_dangle
()
->
String
{
String
::
from
(
"hello"
)
// 直接反回函数的值,不能加分号
}
//编译报错,因为s是在dangle内部创建的,所以当dangle的代码完成时,将释放s。但是我们试图返回对它的引用。这意味着该引用将指向无效的String。Rust不允许我们这样做。
// fn dangle() -> &String {
// let s = String::from("hello");
// &s
// }
}
pub
fn
point_function
()
{
fn
calculate_length
(
s
:
&
String
)
->
usize
{
s
.len
()
}
let
s1
=
String
::
from
(
"hello"
);
///类似c/c++传递指针/引用
let
len
=
calculate_length
(
&
s1
);
///s1在之后还能使用
println!
(
"The length of '{}' is {}."
,
s1
,
len
);
}
pub
fn
copy_function
()
{
let
x
=
5
;
///基本类型在移动时使用copy,x不会失效。
let
y
=
x
;
println!
(
"x = {}, y = {}"
,
x
,
y
);
///使用clone克隆数据,目前先理解为深拷贝
let
s1
=
String
::
from
(
"hello"
);
let
s2
=
s1
.clone
();
println!
(
"s1 = {}, s2 = {}"
,
s1
,
s2
);
}
pub
fn
tuple_function
()
{
let
s1
=
String
::
from
(
"hello"
);
let
(
s2
,
len
)
=
calculate_length
(
s1
);
println!
(
"The length of '{}' is {}."
,
s2
,
len
);
fn
calculate_length
(
s
:
String
)
->
(
String
,
usize
)
{
let
length
=
s
.len
();
// len() 返回字符串的长度
(
s
,
length
)
}
}
rust-exercise/src/simple_array_data_type.rs
0 → 100644
浏览文件 @
2f0f026d
///简单数据类型与数组,所有权
pub
fn
simple_array_data_type
()
{
///--release模式下,整数溢出将会变为最小值
///在u8(0-255)类型下,256变为0,257变为1,依此类推
///默认浮点类型是f64,相当于Java double,IEEE754标准
let
x
=
2.0
;
// f64
let
y
:
f32
=
3.0
;
// f32
///数值运算,与其他语言相同,类型可以自动推断,不用指定类型
// addition
let
sum
=
5
+
10
;
// subtraction
let
difference
=
95.5
-
4.3
;
// multiplication
let
product
=
4
*
30
;
// division
let
quotient
=
56.7
/
32.2
;
// remainder
let
remainder
=
43
%
5
;
let
t
=
true
;
///显示指定类型
let
f
:
bool
=
false
;
///字符类型,Unicode,4bytes
let
c
=
'z'
;
let
z
=
'ℤ'
;
let
heart_eyed_cat
=
'😻'
;
///元组类型,与Scala基本相同,可以推断出类型
let
tup
:
(
i32
,
f64
,
u8
)
=
(
500
,
6.4
,
1
);
let
tup
=
(
500
,
6.4
,
1
);
///提取出元组的每个值
let
(
x
,
y
,
z
)
=
tup
;
println!
(
"The value of y is: {}"
,
y
);
///使用 .获取元组的值,从0下标开始
let
five_hundred
=
tup
.0
;
let
six_point_four
=
tup
.1
;
let
one
=
tup
.2
;
///数组类型,一般在只有固定元素个数的时候使用
let
array
=
[
1
,
2
,
3
,
4
,
5
];
///初始化数组的第二种方法
let
a
:
[
i32
;
5
]
=
[
1
,
2
,
3
,
4
,
5
];
///等价于let a = [3, 3, 3, 3, 3];,意为5个3构成的数组
let
a
=
[
3
;
5
];
///访问数组,同样是从0下标开始
let
first
=
a
[
0
];
let
second
=
a
[
1
];
///Rust通过立即退出而不是允许内存访问并继续操作来保护您免受此类错误的侵害
let
element
=
a
[
0
];
//若下标大于数组索引则运行时检查并报错退出"error: index out of bounds: the len is 5 but the index is 10"
}
///rust String比较复杂
pub
fn
string_function
()
{
let
mut
s
=
String
::
from
(
"hello"
);
s
.push_str
(
", world!"
);
// push_str() 将文字附加到字符串
println!
(
"{}"
,
s
);
//打印 hello, world!
let
s
=
String
::
from
(
"hello"
);
// s进入范围
takes_ownership
(
s
);
// s的值移动到函数,所以在这里不再有效
//println!("{}", s);//编译错误:value borrowed here after move。出借后的s被移动,后续不可用
let
x
=
5
;
// x进入范围
makes_copy
(
x
);
// x将移动到函数
//但是i32是Copy,所以之后还可以使用
println!
(
"{}"
,
x
);
//正常打印
fn
takes_ownership
(
some_string
:
String
)
{
println!
(
"{}"
,
some_string
);
}
//在这里,some_string超出范围并调用`drop`。内存释放
fn
makes_copy
(
some_integer
:
i32
)
{
println!
(
"{}"
,
some_integer
);
}
}
\ No newline at end of file
rust-exercise/src/struct_data_type.rs
0 → 100644
浏览文件 @
2f0f026d
///结构体
pub
fn
struct_data_type
()
{
struct
User
{
username
:
String
,
email
:
String
,
sign_in_count
:
u64
,
active
:
bool
,
}
let
mut
user1
=
User
{
//必须定义为可变的才能修改结构体的内容
email
:
String
::
from
(
"someone@example.com"
),
username
:
String
::
from
(
"someusername123"
),
active
:
true
,
sign_in_count
:
1
,
};
user1
.email
=
String
::
from
(
"anotheremail@example.com"
);
//对应参数名和结构体属性名称相同的,可以省略以减少代码
fn
build_user
(
email
:
String
,
username
:
String
)
->
User
{
User
{
email
:
email
,
username
:
username
,
active
:
true
,
sign_in_count
:
1
,
}
}
//更好的方法是省略参数名,结构体没有顺序要求,与元祖不同,元祖结构体:仅声明类型的结构体
fn
build_user_better
(
email
:
String
,
username
:
String
)
->
User
{
User
{
email
,
username
,
active
:
true
,
sign_in_count
:
1
,
}
}
//创建一个新的结构体user2,并使用user1的某些值
let
user2
=
User
{
email
:
String
::
from
(
"another@example.com"
),
username
:
String
::
from
(
"anotherusername567"
),
active
:
user1
.active
,
sign_in_count
:
user1
.sign_in_count
,
};
//更好的方式是使用 ..语法,其余字段应与给定实例(user1)中的字段具有相同的值
let
user2
=
User
{
email
:
String
::
from
(
"another@example.com"
),
username
:
String
::
from
(
"anotherusername567"
),
..
user1
};
//元祖结构体,没有命名属性字段,仅有类型声明
struct
Color
(
i32
,
i32
,
i32
);
struct
Point
(
i32
,
i32
,
i32
);
let
black
=
Color
(
0
,
0
,
0
);
let
origin
=
Point
(
0
,
0
,
0
);
//此结构体存储切片。而上面的结构体存储的是String类型,下面代码编译会报错,因为使用切片时需要指定生命周期。与使用String拥有所有权不同,&str没有获取所有权而只是借用
// struct User2 {
// username: &str,
// email: &str,
// sign_in_count: u64,
// active: bool,
// }
let
width1
=
30
;
let
height1
=
50
;
fn
area
(
width
:
u32
,
height
:
u32
)
->
u32
{
width
*
height
}
println!
(
"The area of the rectangle is {} square pixels."
,
area
(
width1
,
height1
));
//使用元祖
fn
area_tuple
(
dimensions
:
(
u32
,
u32
))
->
u32
{
dimensions
.0
*
dimensions
.1
}
let
rect1
=
(
30
,
50
);
println!
(
"The area of the rectangle is {} square pixels."
,
area_tuple
(
rect1
)
);
//使用结构体赋予更多含义
#[derive(Debug)]
//使得该结构体能在println!中被打印
struct
Rectangle
{
width
:
u32
,
height
:
u32
,
}
fn
area_struct
(
rectangle
:
&
Rectangle
)
->
u32
{
rectangle
.width
*
rectangle
.height
}
let
rect1
=
Rectangle
{
width
:
30
,
height
:
50
};
println!
(
"The area of the rectangle is {} square pixels."
,
area_struct
(
&
rect1
)
);
//这将会报错,因为该结构体不支持显示:`Rectangle` doesn't implement `std::fmt::Display`
println!
(
"rect1 is {:#?}"
,
rect1
);
//{:?}使用调试模式打印也会报错:`Rectangle` doesn't implement `std::fmt::Debug`,{:#?} 格式化打印
}
\ No newline at end of file
rust-exercise/src/variables_function.rs
0 → 100644
浏览文件 @
2f0f026d
///变量 表达式
pub
fn
variables_function
()
{
//默认i32,带符号32位整数
let
x
=
5
;
println!
(
"The value of x is: {}"
,
x
);
// x = 6; 不可变的,编译不过
// println!("The value of x is: {}", x);
let
mut
y
=
6
;
println!
(
"The value of y is: {}"
,
y
);
y
=
7
;
//可变的变量
println!
(
"The value of y is: {}"
,
y
);
//常量,必须指定类型,不可省略
const
MAX_POINTS
:
u32
=
100_000
;
println!
(
"The value of const value is: {}"
,
MAX_POINTS
);
///阴影允许定义变量与前面重名,前者被遮蔽
///mut与shadowing区别:后者将创建一个新的变量,因此可以改变类型,使用相同的名称,常见用法如下:
//let spaces = " ";
//let spaces = spaces.len();//使用相同名称但类型已经发生变化
///但是对于mut则不能,spaces虽然是可变的,但是类型是字符串类型的
//let mut spaces = " ";
//spaces = spaces.len();
let
i
=
5
;
let
i
=
x
+
1
;
let
i
=
x
*
2
;
println!
(
"The value of x is: {}"
,
i
);
}
pub
fn
try_change_function
()
{
///必须都是mut的,否则编译就会报错,不可变,无法被改变
fn
change
(
some_string
:
&
mut
String
)
{
some_string
.push_str
(
", world"
);
}
let
mut
s
=
String
::
from
(
"hello"
);
change
(
&
mut
s
);
let
mut
s
=
String
::
from
(
"hello"
);
let
r1
=
&
mut
s
;
//let r2 = &mut s;//可变引用只能被出借一次,这里将会编译报错
//println!("{}, {}", r1, r2);
let
mut
s
=
String
::
from
(
"hello"
);
{
let
r1
=
&
mut
s
;
}
// r1在这里超出范围,因此我们可以毫无问题地进行新引用。
let
r2
=
&
mut
s
;
//正常使用,虽然上面已经用过s
let
mut
s
=
String
::
from
(
"hello"
);
let
r1
=
&
s
;
// 没问题,与上面两次mut出借不一样,这里是没有mut,所以对于不可变引用,可以使用多次次,且不可在拥有不可变引用时同时拥有可变引用
let
r2
=
&
s
;
// 没问题
//let r3 = &mut s; // 有问题,不可变在后面却是可变,不允许,编译报错
//println!("{}, {}, and {}", r1, r2, r3);
let
mut
s
=
String
::
from
(
"hello"
);
let
r1
=
&
s
;
// 没问题
let
r2
=
&
s
;
// 没问题
println!
(
"{} and {}"
,
r1
,
r2
);
//在此之后不再能使用r1和r2
let
r3
=
&
mut
s
;
// 没问题,因为r1 r2进入println! 并且在此之后会失效,与所有权有关。
println!
(
"{}"
,
r3
);
}
pub
fn
expr_function
()
{
//赋值需要返回值,rust语句没有返回值,不同于其他语言赋值可以连用
// let x = (let y = 6);
let
x
=
5
;
let
y
=
{
let
x
=
3
;
x
+
1
//返回x+1,且不能用分号,有分号表示这个是语句,没有返回值,无法赋值给y
};
println!
(
"The value of y is: {}"
,
y
);
}
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录