Rust入门
rust
编译:
rustc main.rs
函数声明
fn functionName() {...}
打印文本
println!(...);
println! 是一个rust maro(宏),rust的宏结尾有!
rust的缩进是四个空格而不是tab
代码以;结尾
在windows操作系统编译还包含.pdb文件,里面包含调试信息
rustc知识和编译简单的rust程序,复杂的rust程序要使用cargo编译
使用cargo创建项目
cargo new project_name
Cargo.toml :cargo的配置文件
rust的包称作crate
构建项目:cargo build
构建并运行项目:cargo run
检查代码:cargo check
为发布构建项目:cargo build --release
变量
不可变变量
let a = 123;
可变变量
let mut a = 123;
不可变变量可以被重新声明
let a = 123; let a = 456;
常量
const a: i32 = 123;
复合类型
let tup: (i32, f64, u8) = (500, 6.4, 1);
数组
let mut a: [i32; 5]; let mut a = [3; 5]; //带初始化
函数
fn add(a: u32, b: i32) -> i32 {
return a + b;
} 函数体表达式(函数体表达式不能使用return关键字):
let y = {
let x = 3;
x + 1;
}; 条件语句
同go
循环
fn main() {
let a = [10, 20, 30, 40, 50];
for i in 0..5 {
println!("a[{}] = {}", i, a[i]);
}
for i in a.iter() {
println!("{}", i)
}
} 死循环
loop {
...
} 循环的返回值
let res = loop {
let mut i = 0;
...
if ... {
break i;
}
...
}; 所有权
let s1 = String::from("hello");
let s2 = s1; //s1的资源将被释放
println!("{}, world!", s1); // 错误!s1 已经失效 克隆
fn main() {
let s1 = String::from("hello");
let s2 = s1.clone(); //s1未被移动
println!("s1 = {}, s2 = {}", s1, s2);
} 租借所有权:租借的值禁止修改
fn main() {
let s1 = String::from("hello");
let mut s2 = &s1;
let s3 = s2;
s2 = &s3; // 重新从 s3 租借所有权
println!("{}", s2);
} 可变引用(不允许多重引用)
fn main() {
let mut s1 = String::from("run");
// s1 是可变的
let s2 = &mut s1;
// s2 是可变的引用
s2.push_str("oob");
println!("{}", s2);
} 切片
let s1 = String::from("hello")
let slice = s1[0..3];
let s2 = &s1[..]; 结构体
struct foo {
a: String,
b: i32,
c: f32
} 有这样一种情况:你想要新建一个结构体的实例,其中大部分属性需要被设置成与现存的一个结构体属性一样,仅需更改其中的一两个字段的值,可以使用结构体更新语法:
let site = Site {
domain: String::from("www.runoob.com"),
name: String::from("RUNOOB"),
..runoob
}; 注意:..runoob 后面不可以有逗号。这种语法不允许一成不变的复制另一个结构体实例,意思就是说至少重新设定一个字段的值才能引用其他实例的值。
元组结构体:
struct Point(f64, f64);
fn main() {
struct Point(f64, f64);
let origin = Point(0.0, 0.0);
println!("origin = ({}, {})", origin.0, origin.1);
} 输出一整个结构体
#[derive(Debug)]
struct Rectangle {
width: u32,
height: u32,
}
fn main() {
let rect1 = Rectangle { width: 30, height: 50 };
println!("rect1 is {:?}", rect1);
} 如第一行所示:一定要导入调试库 #[derive(Debug)] ,之后在 println 和 print 宏中就可以用 {:?} 占位符输出一整个结构体,如果属性较多的话可以使用另一个占位符 {:#?}
接口:
接口方法的第一个参数必须是 &self,不需声明类型,因为 self 不是一种风格而是关键字。
impl Rectangle {
fn area(&self) -> u32 {
self.width * self.height
}
} 单元结构体
结构体可以只作为一种象征而无需任何成员:
struct UnitStruct;
match语句
match 块也可以当作函数表达式来对待,它也是可以有返回值的:
match 枚举类实例 {
分类1 => 返回值表达式,
分类2 => 返回值表达式,
...
} 对非枚举类进行分支选择时必须注意处理例外情况,即使在例外情况下没有任何要做的事 . 例外情况用下划线 _ 表示(default)
fn main() {
let t = "abc";
match t {
"abc" => println!("Yes"),
_ => {},
}
} 添加依赖
[dependencies] rand = "0.3.14"
案例:
use std::io; //prelude
use std::cmp::Ordering;
use rand::Rng; //trait
fn main() {
println!("猜测一个数");
let num = rand::thread_rng().gen_range(1, 101); //0.8以后的参数要写成(0..101)格式
//println!("神秘数字是{}", num);
loop {
let mut guess = String::new();
io::stdin().read_line(&mut guess)
.expect("读取失败"); //捕获错误
/*
read_line返回io:Result 是一个enum,有两个变体Ok和Err,Ok代表读取成功,反之失败
*/
let guess:u32 = match guess.trim().parse() {
Ok(num) => num, //转换成功则赋值
Err(_) => continue, //转换失败则跳过本次循环重新输入
};
//模式匹配
match guess.cmp(&num) {
Ordering::Less => println!("太小了"),
Ordering::Greater => println!("太大了"),
Ordering::Equal => {
println!("猜对了");
break;
},
}
}
} mod front_of_house {
pub mod hosting {
pub fn add_to_waitlist() {}
}
}
//模块是一种树形结构,crate是根节点,方法可以在子mod中
pub fn eat_at_restaurant() {
crate::front_of_house::hosting::add_to_waitlist();
} fn serve_order() {}
mod back_of_house {
fn fix_incorrect_order() {
cook_order();
super::serve_order(); //super调用上级目录
}
fn cook_order() {}
} pub struct
pub声明struct
- struct是公共的
- struct的字段默认是私有的
mod back_of_house {
pub struct Breakfast {
pub toast: String,
seasonal_fruit: String,
}
impl Breakfast {
pub fn summer(toast: &str) -> Breakfast {
Breakfast {
toast: String::from(toast),
seasonal_fruit: String::from("peaches"),
}
}
}
}
pub fn eat_at_restaurant() {
let mut meal = back_of_house::Breakfast::summer("Xxx");
meal.toast = String::from("Wheat");
println!("{}", meal.toast);
} pub enum
pub声明enum后enum的所有变体也都是pub的
use关键字
use导入的名称默认是私有的,使用pub声明可让外部也使用
使用外部包
在Cargo.toml里添加依赖的package然后在条目中使用use
如果导包出现block错误,可以删除.cargo目录下的.package-cache文件
查看所有文件包括隐藏文件:ls -al
换源:
再.cargo目录下创建config文件并写入:
[source.crates-io] registry = "https://github.com/rust-lang/crates.io-index" replace-with = 'ustc' [source.ustc] registry = "git://mirrors.ustc.edu.cn/crates.io-index"
使用嵌套路径包含相同前缀的导包
use std::{cmp::Ordering, io}; 针对特殊的引用:
use::io{self, Write};
/*
相当于
use std::io;
use std::io::Write;
*/ 引入所有公共条目(谨慎使用,一般用于tests模块):
use std::collections::*;
容器
vector
- Vec<t> vector</t>
创建
let v: Vec<i32> = Vec::new();
使用宏创建vector
let v = vec![1, 2, 3];
添加元素
let mut v = Vec::new(); v.push(1);
获取元素
let item: &i32 = &v[2]; //通过索引
match v.get(2) {
Some(item) => println!("{}", item);
None -> println!("There is no the element");
} fn main() {
let mut v = Vec::new();
for i in 0..10 {
v.push(i + 1);
}
for i in 0..10 {
println!("{}", v[i]);
}
for i in &mut v {
*i += 1;
}
for i in v {
print!("{} ", i);
}
} 不能同时对元素进行可变解引用和不可变解引用
泛型
编写函数求出数组中最大值
trait Comparable {
fn compare(&self, object: &Self) ->i8;
}
fn max<T: Comparable>(array: &[T]) ->&T{
let mut maxi = 0;
for i in 0..array.len() {
if array[i].compare(&array[maxi]) > 0 {
maxi = i;
}
}
&array[maxi]
}
impl Comparable for f64 {
fn compare(&self, object: &f64) ->i8 {
if &self > &object { 1 }
else if &self == &object { 0 }
else { -1 }
}
}
impl Comparable for i32 {
fn compare(&self, object: &i32) ->i8 {
if &self > &object { 1 }
else if &self == &object { 0 }
else { -1 }
}
}
fn main() {
let a = [0, 1, 2, 3];
let maxn = max(&a);
println!("{}", maxn);
}
查看8道真题和解析
