当前位置:   article > 正文

Rust笔记_rust 生成1到100的随机数

rust 生成1到100的随机数

前言

弱小和无知不是生存的障碍,傲慢才是

参考:

Rust 程序设计语言:https://rust.bootcss.com/

Rust程序设计语言重编版:http://shouce.jb51.net/rust-book-chinese/index.html

Runoob—Rust教程:https://www.runoob.com/rust/rust-tutorial.html

B站视频—Rust编程语言入门教程—杨旭:https://www.bilibili.com/video/BV1hp4y1k7SV?share_source=copy_web

一、Rust安装

边看B站视频边看笔记效果更佳

https://www.bilibili.com/video/BV1hp4y1k7SV?share_source=copy_web

1.2节介绍了安装Rust

Windows + R cmd

rustc --version

二、使用Cargo创建项目

1、查看Cargo版本

Windows + R cmd

cargo --version

2、创建Cargo项目

cargo new hello_cargo[项目名]

3、构建(编译)Cargo项目

cargo build

4、构建(编译)并运行Cargo项目

cargo run

先编译后运行,如果编译过了,直接运行可执行二进制文件

修改源文件会重新编译

该二进制文件会在这个目录下

hello_cargo[项目名]\target\debug\hello_cargo.exe

5、检查代码

cargo check

  • cargo check,检查代码确保能通过编译,但是不产生任何可执行文件

  • cargo check 要比 cargo build 快很多

    编写代码可以连续反复使用cargo check 检查代码,提高效率

6、为发布构建

cargo build --release

  • 编译时会进行优化
  • 代码会运行的更快,但编译时间更长
  • 会在 target\release 而不是 target\debug 下生成可执行文件

两种构建方式一个为了开发,一个为了发布

三、猜数游戏

1、输入一个数能打印出来

1)前置知识

声明变量

mut 将 “不可变值” 变为 “可变值”

将a的值赋值给b
	let a = 1;
    let b = a;
    println!("{}",a);//输出宏的传参
    println!("{}",b);
输出:
	1
	1

如果用另一种方式,先声明,再赋值
	let a = 1;
	let b = 0;
	b = a;
会报错,因为所有的声明,默认是 immutable 不可变的
需要加 mut
	let a = 1;
    let mut b = 0;
    b = a;
    println!("{}",a);
    println!("{}",b);

注意:不能 let b ,所有的声明都要有初始值
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
读取输入

io::stdin().read_line(&mut guess).expect("无法读取行");

io下的stdin()下的read_line()方法:将用户一行输入放到字符串中,也就是 guess 中

read_line()会返回io::Result<usize> Result这个枚举类型中有两个"变体"(枚举类型中的固定值称作变体)

OkErr

返回的是 Ok,表示操作成功了,附加成功的字符串

如果返回的是 Err,表示操作失败了,附加失败的字符串以及报错信息

然后调用.expect()方法

如果read_line()返回的io::Result实例的值是Ok,那么expect()会提取Ok的附加值,作为结果返回给用户

如果read_line()返回的io::Result实例的值是Err,那么expect()会把程序中断,并把传入的字符串信息显示出来

输出

println!("你猜测的数是{}",guess);{ } 占位符

2)代码

use std::io;

fn main() {

    println!("猜数");

    let mut guess = String::new();

    io::stdin().read_line(&mut guess).expect("无法读取行");

    println!("你猜测的数是{}",guess);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

2、生成一个1~100之间的随机数

1)前置知识

导入生成随机数的包

Rust中的库 叫做 crate

官方的库

https://crates.io/

在Cargo.toml 文件中引入

[dependencies]
rand = "^0.3.14"
  • 1
  • 2

^表示任何与这个版本公共API兼容的版本都可以

启动这个包

在VsCode中,引入包后运行这个命令会帮你构建一些

Ctrl + Shift + P

>rust

Rust: Start the Rust server

更改引入包的版本

如果Cargo.toml文件引入的

[dependencies]
rand = "0.3.14"
  • 1
  • 2

那么在你第一次构建的时候

会在Cargo.lock这个文件写入所有依赖项的版本

并且会写入最新版本

比如说 在Cargo.toml引入的版本rand = "0.3.14"

那么会在Cargo.lock写入0.3版本的的最新小版本

[[package]]
name = "guess_number"
version = "0.1.0"
dependencies = [
 "rand 0.3.23",
]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

再次构建的时候就会先查看Cargo.lock这个文件里面的版本

在代码中引入包

use rand::Rng;

这个包是一个trait你可以把它想成接口

而在代码中引入包相当于一个类实现一个接口

所以如果你引入,而不用就会报错

gen_range()方法

gen_range(1,101)会在 [ 1 , 101 )之间生成随机数,1-100之间包含1和100(左闭右开 )

2)代码

use std::io;
use rand::Rng;

fn main() {

    println!("猜数!!!");

    let secret_number = rand::thread_rng().gen_range(1,101);

    println!("生成随机数:{}",secret_number);

    println!("请输入你要猜的数字:");

    let mut guess = String::new();

    io::stdin().read_line(&mut guess).expect("无法读取行");

    println!("你猜测的数是{}",guess);
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

3、比较生成的随机数和输入数字

1)前置知识

引入Ordering

Ordering有三个变体LessGreaterEqual

两个数进行比较

guess.cmp(&secret_number)是用 guess 和 secret_number 进行比较,这个方法会返回一个Ordering

match表达式,可以让我们根据cmp()方法返回的Ordering的值来决定我们下一步做什么

一个match表达式是由多个手臂(arm)或者叫分支组成的,有点像switch

每个手臂含有一个用于匹配的模式这里就是LessGreaterEqual

如果match后面紧跟着的值与某一个 arm 的模式匹配,那么就会执行这个 arm 里面的代码

match是按从上到下的顺序进行匹配的

类型转换

guess.cmp(&secret_number)中的 guess 你输入的是字符串,而 secret_number 是随机的整数,进行比较会报错

因此要把 guess 变为整数进行比较

let guess: u32 = guess.trim().parse().expect("请输入整数");

guess.trim()会删除空格、tab、以及回车(输入时候按回车就会有 \n 输入)

parse()会把输入的字符串解析,有i32 u32 i64,我们这里选择解析成u32

let guess: u32在变量后面加 : u32

2)代码

use std::io;
use rand::Rng;
use std::cmp::Ordering;

fn main() {

    println!("猜数!!!");
    let secret_number = rand::thread_rng().gen_range(1,101);
    println!("生成随机数:{}",secret_number);
    println!("请输入你要猜的数字:");
    let mut guess = String::new();
    io::stdin().read_line(&mut guess).expect("无法读取行");
    println!("你猜测的数是{}",guess);

    let guess: u32 = guess.trim().parse().expect("请输入整数");

    match guess.cmp(&secret_number){
        Ordering::Less => println!("太小了"),
        Ordering::Greater => println!("太大了"),
        Ordering::Equal => println!("猜对了"),
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

Ctrl+左键 查看示例注意:

把下面的代码注释掉,默认是i32

TPDIF1.png

当把 guess 字符串解析为u32时,secret_number也变为了u32

TPrFOg.png

4、多次猜测(终版)

1)前置知识

设置无限循环

loop{}

结束循环

break;结束全部循环

continue;结束本次循环

如何输入字符串不会中止程序

原本的程序

let guess: u32 = guess.trim().parse().expect("请输入整数");

如果输入字符串,会直接抛出异常中止程序

我们想要遇到异常,不结束程序,并且告诉他输入数字

    let guess: u32 = match guess.trim().parse() {
        Ok(num) => num,
        Err(_) => {
            println!("输入数字!");
            continue;
        }
    };
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

guess.trim().parse()的返回值是 Result

Result 有两个变体 Ok 和 Err

Ok 的情况下,正常赋值

Err 的情况下,告诉用户输入数字,并且结束本次循环(然后继续从头走循环)

2)代码

use std::io;
use rand::Rng;
use std::cmp::Ordering;

fn main() {

    println!("猜数!!!");
    let secret_number = rand::thread_rng().gen_range(1,101);
    println!("生成随机数:{}",secret_number);

    loop{
        println!("请输入你要猜的数字:");
        let mut guess = String::new();
        io::stdin().read_line(&mut guess).expect("无法读取行");
        println!("你猜测的数是{}",guess);
    
        let guess: u32 = match guess.trim().parse() {
            Ok(num) => num,
            Err(_) => continue,
        };
    
        match guess.cmp(&secret_number){
            Ordering::Less => println!("太小了"),
            Ordering::Greater => println!("太大了"),
            Ordering::Equal => {
                println!("猜对了");
                break;
            }
        }
    }

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

四、通用的编程概念

1、变量与可变性

  • 声明变量用let关键字
  • 默认情况下,变量是不可变的(immutable)
  • 声明变量时,在变量前加上mut,就可使变量可变 Ctrl+左键 查看示例

1)变量与常量

常量(constant),常量在绑定值以后也是不可变的,但它与不可变的变量有很多区别

  • 不可以使用 mut ,常量永远都是不可变的

  • 声明常量使用 const 关键字,它的类型必须被标注

  • 常量可以在任何作用域内进行声明,包括全局作用域

  • 在程序运行期间,常量在其声明的作用域内一直有效,因此可以作为不同代码之间共享值

    const MAX_POINTS: u32 = 10_0000;
    
    fn main() {
        const MAX_POINTS: u32 = 10_0000;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
  • 常量只可以绑定到常量表达式,无法绑定到函数的调用结果或只能在运行时才能计算的值(就是在编译期就确定了)

命名规范:Rust 里常量使用全大写字母,每个单词之间用下划线分开,例如:

const MAX_POINTS: u32 = 10_0000

数字增加下划线只是为了增加可读性

2)Shadowing

可以使用相同的名字声明新的变量,新的变量就会 shadow(隐藏) 之前声明的同名变量

在后续的代码中这个变量名就是新的变量

shadow :

fn main() {

    let a = 2;
    let a = a + 1;
    let a = a * 3;
    println!("The value a is :{}",a);

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

mut:

fn main() {

    let mut a = 2;
    a = a + 1;
    a = a * 3;
    println!("The value a is :{}",a);

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

但是shadow 和把变量标记为 mut 是不一样的

使用let声明的同名新变量,也是不可变的

使用let声明的同名新变量,它的类型可以与之前不同

shadow :

fn main() {

    let str = "     ";
    let str = str.len();
    println!("长度{}",str);

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

mut:

fn main() {

    let mut str = "     ";
    str = str.len();//报错:把一个整数赋给字符串
    println!("长度{}",str);

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

2、数据类型

Rust 是静态编译语言,在编译时必须知道所有变量的类型

  • 基于使用的值,编译器通常能够推断出它的具体类型 Ctrl+左键 查看示例

  • 但如果可能的值比较多(例如把 String 转成整数的 parse() 方法),就必须添加类型的标注,否则编译会报错

    let str: u32 = "2".parse().expect("Not a number");

1)标量类型

一个标量类型代表一个单个的值

Rust 有四个主要的标量类型:

整数类型
  • 整数类型没有小数部分
  • 例如 u32就是一个无符号的整数类型,占据 32 位的空间
  • 无符号整数类型以 u 开头(无符号指的是,非负)
  • 有符号整数类型以 i 开头

i:有符号整数范围
[ − ( 2 n − 1 ) , 2 n − 1 − 1 ] [-(2^n - 1) , 2^{n-1} - 1] [(2n1),2n11]
u:无符号整数范围

[ 0 , 2 n − 1 − 1 ] [0,2^{n-1} - 1] [0,2n11]

如表格所示,每种都分 i 和 u 以及固定的位数

LengthSignedUnsigned
8-biti8u8
16-biti16u16
32-biti32u32
64-biti64u64
128-biti128u128
archisizeusize

表格最后的 isize 和 usize类型

isize 和 usize类型的位数由程序运行的计算机的架构决定:

如果是 64 位计算机,那就是 64 位

使用 isize 和 usize 的主要场景是对某种集合进行索引操作(不常见)

整型字面值

为了便于辨识整型字面值,可以在字面值中加入 _ 用作数字之间的分隔,如:1_000_000,_ 所起的作用仅仅是方面代码的阅读,它与1000000表示的相同的数值;另外除了字节字面值(即以0,1序列表示的数值),其他类型的整型字面值都可以加上类型说明符作为后缀以标识数值类型,如:255u8, 1024i64或者1024_i64等。

let a = 255u8

一个数字,可以采用不同的进制表示,如十进制,十六进制,八进制和是二进制等。区分这些不同进制的数的方式是根据字面值所带的前缀,如下表:

字面值类型示例
二进制0b100_0001
八进制0o101 //零欧
十进制65
十六进制0x41
字节(只能是u8)b’A’

如果你不太清楚使用哪种数据类型,整数默认类型就是i32

整数溢出

例如:u8的范围是 0 ~ 255,如果你把一个u8变量的值设称 256,就会发生整数溢出:

这分为两种情况

  • 调试模式下编译:Rust 会检查整数溢出,如果发生溢出,程序在运行时就会panic(恐慌)

  • 发布模式下(–release)编译:Rust 不会检查可能导致 panic 的整数溢出

    如果溢出发生:Rust 会执行“环绕”操作

    256变为0,257变为1

    但程序不会 panic浮点类型

浮点类型

Rust 有两种基础的浮点类型

f32,32位,单精度

f64,64位,双精度

    let a = 1.0;//f64
    let a :f32 = 1.0;//f32
  • 1
  • 2

Rust 的浮点类型使用了 IEEE-754 标准来表述

默认会使用 f64 类型

数值操作

加减乘除余

跟其他语言一样,不多赘述

    let sum = 5 + 10;

    let difference = 97.8 - 24.1;

    let producet = 4 * 30;
    
    let quotient = 56.7 / 32.1;

    let reminder = 54 % 5;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
布尔类型
  • Rust 的布尔类型:truefalse
  • 1个字节大小
  • 符号是bool
    let t = true;

    let f :bool = false;
  • 1
  • 2
  • 3
字符类型
  • Rust 语言中 char类型被用来描述语言中最基础的单个字符

  • 字符类型的字面值使用单引号

  • 占用 4 个字节大小 (1个字节 = 1 byte = 8 位 = 8 bit 比特 = 8 个 0,1)

  • 是 Unicode 标量值,可以表示比 ASCⅡ 多得多的字符内容:拼音,中日韩文,零长度空白字符,emoji表情等

    范围:

    U+0000 ~ U+D7FF

    U+E000 ~ U+10FFFF

  • 但 Unicode 中并没有 “字符” 的概念,所以直觉上认为的字符也许与 Rust 中的概念并不相符

请注意字符类型是单引号

如果let b :char = "₦" 这样声明会报错

    let a = 'n';

    let b :char = '₦';

    let c = '
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/702724
推荐阅读
相关标签