安装rust,我选择在wsl中安装:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
查看版本:
shellrustc --version
查看文档:
shellrustup doc
源码:
rustfn main(){
println!("Hello World!");
}
编译:
shellrustc main.rs
注意事项:
rust语言特点:ahead-of-time预编译,可以将编译完成的rust程序直接发送给未安装rust的电脑运行。
注意:
rustc只适用于简单的,小型的rust程序。复杂的则需要cargo
cargo是rust构建系统和包管理工具
shell~/rust_learning 19:21:10 ─╮ ❯ cargo --version ─╯ cargo 1.75.0 (1d8b05cdd 2023-11-20)
可以通过cargo new *** .rs创建项目:
他会直接在当前目录下创建一个新的目录:
里面包含:
src以及该项目的配置文件
.gitgnore是仓库初始文件,Cargo.toml是该项目的配置文件:
里面包含文件依赖,版本信息等
运行:
shellcargo run//类似docker run
题目信息:
第一步,创建项目:
shell❯ cargo new guessing ─╯ Created binary (application) `guessing` package
第二步,编写源码:
rustuse std::io;//因为我们下面
fn main() {
println!("let us play a game!");
println!("guess what is next number!");
let mut guess = String::new();
io::stdin().read_line(&mut guess).expect("error");
println!("this is your guess: {}", guess);
}
代码详解:
rustuse std::io;//因为我们下面引用了read_line函数,他是IO库中的函数,而IO库又是STD库中的函数,所以我们再调用read_line函数的时候需要用 USE 导入该库,因为这一个库没有被preclude
fn main() {
println!("let us play a game!");
println!("guess what is next number!");//注意println!不是函数,是一个宏
let mut guess = String::new();
//let 用于声明变量
//mut关键字表明该变量是可修改的,而在rust中所有变量在申明时默认都是immuteable,不可修改的
//举个例子:如果let foo = 1;声明foo为1,那么我们不可以再foo = 2;对其赋值。
//::表明new是String类型的关联函数,关联函数就是指,他是针对这一类型来实现的,而不是针对某一个实例实现的。String是标准库中的,采用utf-8格式。
io::stdin().read_line(&mut guess).expect("error");
//如果未申明use std::io,可以换一种写法:std::IO::read_line...这样子可以达到同样的效果。注意read_line返回的值为有两种:OK err,这里.expect就是指当readline返回值为err时就输出“error”;然后就是这里关于引用&,这样子引用的是同一块数据区域,注意read_line函数第二个参数规定了是String类型,只能用字符串类型的参数,引用&在rust里面也是默认不可更改,这也是加mut的原因。
println!("this is your guess: {}", guess);
//{}为占位符,类似C语言中的%d等等。
}
在rust中,我们为了生成随机数,需要外部导入一个lib类型的库 rand,这个库要添加到cargo.toml的[dependencies]部分中,如下:
然后我们重新编译一下:
可以看到,这里已经成功将rand依赖导入
导入库的过程大致如下:
先将crates.io这个网址最新的索引下载下来,就是一个注册表,然后更新注册表,然后cargo就会检查dependieces下有哪些库未下载,然后再下载,同样的因为rand库也有一个依赖,所以我们可看到上图中第一个位置是libc,这就是rand库的依赖。
简单源码:
rustuse std::io;
use rand::Rng;//trait 类似接口
fn main() {
println!("let us play a game!");
println!("guess what is next number!");
println!("this is the number you should know!");
let secretnumber = rand::thread_rng().gen_range(1..101);//范围[1,101),这里最新版的rand库,要求范围这么写,旧版本(1,101);
println!("生成的随机数是 {}",secretnumber);
println!("plz guess the number.");
let mut guess = String::new();
io::stdin().read_line(&mut guess).expect("error");
println!("this is your guess: {}", guess);
}
注意:RUST严格区分大小写;
rustuse std::io;
use rand::Rng;//trait 类似接口
use std::cmp::Ordering;
fn main() {
println!("let us play a game!");
println!("guess what is next number!");
println!("this is the number you should know!");
let secretnumber = rand::thread_rng().gen_range(1..101);//范围[1,101)
println!("生成的随机数是 {}",secretnumber);
println!("plz guess the number.");
let mut guess = String::new();
io::stdin().read_line(&mut guess).expect("error");
println!("this is your guess: {}", guess);
let guess:u32 = guess.trim().parse().expect("error");//因为之前guess在申明时直接就是String类型,而secretnumber是整数型,无法直接比较,会报错,所以这里我们需要
//将String类型转为整形,trim是为了将字符串两边空格等不显示字符去掉,parse()转整形,如果有xy等字符,转型失败,同read_line的expect用法。
//这样的同名变量会隐藏之前一个变量(shadow),其统属范围以覆盖位置为结尾。let guess:u32显示类型,同样的为了比较,secretnumber也会被转型从i32转为u32
match guess.cmp(&secretnumber){
Ordering::Less => println!("Too small"),
Ordering::Greater => println!("Too big"),
Ordering::Equal => println!("you win!"),//注意match的分支arm,结尾需要以,结尾.
}
}
这节主要就是学习了:
RUSTuse std::io;
use rand::Rng;//trait 类似接口
use std::cmp::Ordering;
fn main() {
println!("let us play a game!");
println!("guess what is next number!");
println!("this is the number you should know!");
let secretnumber = rand::thread_rng().gen_range(1..101);//范围[1,101)
println!("生成的随机数是 {}",secretnumber);
loop{//无限循环
println!("plz guess the number.");
let mut guess = String::new();
io::stdin().read_line(&mut guess).expect("error");
println!("this is your guess: {}", guess);
let guess: u32 = match guess.trim().parse() {
Ok(num) => num,//将解析成功的数字赋给guess
Err(_) => continue,//_通配符表示忽略报错信息,然后continue
};//为了避免输入无法转型的字符导致的退出,因为parse返回也为result枚举型,可以用match分支实现
match guess.cmp(&secretnumber) {
Ordering::Less => println!("Too small"),
Ordering::Greater => println!("Too big"),
Ordering::Equal => {
println!("you win!");
break;//这里利用break实现在猜对后推出loop的效果
}
}
}
}
这里第一时间,我想的是直接在read_line后面match,然后报错了,发现原来是result类型不一致:
以下是chatgpt给出的回答:
在你的代码中,
read_line
和parse
都返回Result
类型,但它们代表的不同操作,因此包含的信息也不同。
io::Result
(read_line
的返回类型):
io::Result
是std::io
模块中的一个特定Result
类型,用于表示 I/O 操作可能的成功或失败。io::Result
的Ok
分支包含成功时的结果,通常是读取的字节数或其他 I/O 相关信息。io::Result
的Err
分支包含错误信息,它可能是由于文件不存在、权限问题、或其他 I/O 错误而导致的失败。例如,在你的代码中,
io::stdin().read_line(&mut guess).expect("Error")
尝试从标准输入读取一行,并返回io::Result
,其中Ok
包含读取的字节数,而Err
包含可能的 I/O 错误信息。
Result<u32, ParseIntError>
(parse
的返回类型):
parse
函数返回的Result
是一个泛型类型,它表示解析字符串为数字可能的成功或失败。Ok
分支包含成功时的解析结果,这里是一个u32
类型的数字。Err
分支包含解析失败时的错误信息,通常是一个实现了std::error::Error
trait 的类型,比如ParseIntError
。在你的代码中,
match guess.trim().parse()
用于处理parse
的返回结果,其中Ok(num)
包含解析成功时得到的数字,而Err(_)
包含解析失败的错误信息。在这里,continue
语句用于跳过当前迭代并提示用户重新输入,表示解析失败。
所以这里只能在parse这里使用match分枝。
常量在被定义后和默认immut的变量一样不可更改,但依旧有很多区别:
在程序运行期间,常量在其声明的作用域中一直有效
命名规范:Rust里面常量必须是使用大写字符,并且只能用下划线隔开,例:
定义例:
const MAX_POINTS:u32 = 100_00;”_“ 在RUST可用于增加可读性。
shadowing(隐藏)
rust let mut y = 6;
y = y+1;//不会报错
let y = y+8;
y = y+1;//这里会报错,重新声明也需要加mut
usize表示与自己电脑相同位数。
RUST是静态编译语言,所以在编译时必须知道所有的变量的类型:
基于使用的值,编译器能推断出大部分的类型
但对于如Parse()转型等方法使用过程中,就需要显式的写出
rustlet mut guess = "42";
let guess:u32 = guess.parse().expect("err");
因为对于42我们可以转为i32和u32等等,所以我们需要显示的写出类型。
一个标量代表一个单个的值
Rust有四个主要的标量类型:
整数类型
布尔类型
浮点类型
字符类型
注意一字节8位
默认类型时i32,性能速度相当快。
例如:u8的范围是0-255,如果你把一个u8的变量设为256,那么:
Rust有两种浮点类型,也就是含有小数部分的类型
分别是:
Rust使用IEEE-754(计组:规格化)标准来描述,并使用f64为默认类型。
与其他语言一致,不细说。
两种值:
false 和true
均占一字节大小。
Rust中char类型被用来描述语言中最基础的单个字符。
字符类的字面值使用单引号
占用4字节
是unicode标量值,可以表示比ASCII多的字符内容:拼音,中日韩文,零长度空白字符,emoji表情等等。
rustlet hui:(i32,f64,char) = (32,5.4,'a');
println!("{},{},{}",hui.0,hui.1,hui.2);
//输出
32,5.4,a
rustlet hui:(i32,f64,char) = (32,5.4,'a');
let (x,y,z) = hui;
println!("{},{},{}",hui.0,hui.1,hui.2);
println!("{},{},{}",x,y,z);
//输出
32,5.4,a
32,5.4,a
rustlet hui:(i32,f64,char) = (32,5.4,'a');
println!("{},{},{}",hui.0,hui.1,hui.2);
//输出
32,5.4,a
let a[u32;5] = [1,2,3,4,5];
[类型:长度]
或者:
let a[3;5] = [3,3,3,3,3];
[值:长度]
通过中括号的索引访问,与其它语言中一致;
注意简单的数组越界在编译时,rust会直接报错;当然复杂的越界不会;
最大为12时:
报错
不报错:
snake case;
所有字母都是小写,单词之间使用下划线分开。
rustfn new_function(x:i32,y:u32);//这里的参数z,y也就是形参
这里有一点很重要:
注意这里y语句部分,x+3没有以分号结尾,所以这里其实相当于y = x + 3,只不过这里x的初值为1;只要看这里有没有返回值就可以,如果加了”;“,呢么这块语句就会被判定为没有返回值,y也就会被赋空值;并爆错,无法打印。
并且我们可以看到,这里x没有shadow前一个x,它的作用域只在花括号中。
rustfn six() -> i32{
6
}
fn plus_six(x:i32) -> i32{
x + 6
}
let yu = six();
let xu = plus_six(6);
println!("the value of yu {}",yu);
println!("the value of yu {}",xu);
//输出
the value of yu 6
the value of yu 12
//
或者/**/
注意:如果使用了多于一个else if,最好使用match语句重构你的代码。
反复执行一段代码,直至手动停止,或者break;
每次执行前都判断一次条件
最为重要的循环方法
通过Range生成,1,2,3三个数,并用rev(),逆序输出。
本文作者:Hyrink
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!