Rust从入门到跑路 - 第三篇 猜数字游戏(1)

756 阅读4分钟

这是我参与更文挑战的第3天,活动详情查看: 更文挑战

Rust是一门赋予每个人构建可靠且高效软件能力的语言。 下面所有的例子以及代码都是以Mac环境,编辑器是vscode,如果遇到什么问题,欢迎加入交流群,一起交流。

Rust猜数字游戏 VS NodeJS猜数字游戏

依稀记得当初学习NodeJS的时候,也是这个猜拳游戏来认识NodeJS的。相信大家大家写NodeJS的猜数字游戏手到擒来,我就不再赘述。那看看Rust应该怎么实现。

输入输出相同数字

输出大家已经掌握了,那怎么能接收从终端的输入呢,这是候就要一个io库,那直接导入io库。使用use关键字实现导入。::是相当于模块的一级级路径分割,当然也可以泛型指定和关联函数等,在这里是路径分割。(不要问什么,问就是 -> 规定)。PS:后续回详细介绍。

use std::io // 类似于并不是等价 const { io } = require('std') 因为module概念不一样
// use std::io::stdin 或者 use std都是可以的 语法后面再讲,这里介绍只是为了消除你心中的疑虑
fn main () {
    println!("欢迎来到猜数字游戏");
    io::stdin().read_line(&mut str); 
}

stdin函数返回一个std::io::Stdin的实例,调用实例上的read_line方法,并用变量str接收。那&mut是什么鬼?接着往下看。

创建一个可变变量和不可变变量

Rust声明一个变量使用let关键字,在JavaScriptlet关键字创建的变量是可变的,但Rust是相反的,要想创建一个不可变的变量,必须使用mut关键字。那我们声明一个变量str

use std::io;
fn main() {
    println!("欢迎来到猜数字游戏");
    let mut str;
    stdin().read_line(&mut str);
}

这时候我们执行在终端执行cargo build(等价于rustc main.rs),发现报错了,为什么会报错呢?因为rust是一门强类型语言,所以声明变量必须初始化。由于终端输入的是字符串,所以我们初始化一个字符串。

use std::io;
fn main() {
    println!("欢迎来到猜数字游戏");
    // new是String的一个关联函数,用来创建一个新的空字符串,并将空字符串赋值给可变变量str
    let mut str = String::new(); // 类似于 JavaScript中new String()
    stdin().read_line(&mut str);
}

看到这里,大家可能会问:既然str已经是一个可变变量,为什么要使用&mut,这里其实有一个所有权的概念(后面会讲 非常核心),先看一下read_line的实现:

pub fn read_line(&self, buf: &mut String) -> io::Result<usize> {
        self.lock().read_line(buf)
}

大白话描述的是read_line函数在传参的时候,实参str将绑定的资源String::new()借给buf使用,实际上就是对内存权限交给bufbuf对资源内存(String::new())可读写。也就是将str对资源的所有权借给buf去用。

用JavaScript解释呢,就是调用函数传递的是一个对象,且函数可以修改原来的对象。

处理异常

这时候我们可以增加一行输出代码,并执行cargo build

fn main () {
    // ...
    println!("你猜的数字是: {}", str);
}

忽然发现报了一个警告,但并不影响程序的执行,这时候执行:cargo run(等价于 ./main),发现我们想要的结果已经出来了,我们在终端上输入数字并回车,发现输出的数字和你输入的数字是相同的。但是这个警告在这让有代码洁癖的我们十分难受,怎么给它消除掉呢?上面我们发现read_line返回的是Result对象,Result的成员是 OkErrOk成员表示操作成功,内部包含成功时产生的值。Err成员则意味着操作失败,并且包含失败的前因后果。这些Result类型的作用是编码错误处理信息。Result类型的值,像其他类型一样,拥有定义于其上的方法。io::Result的实例拥有expect方法。所以我们在增加一个expect方法就好。所以完整代码是:

use std::io;
fn main() {
    println!("欢迎来到猜数字游戏");
    let mut str = String::new();
    io::stdin().read_line(&mut str).expect("接收数字失败,请重新输入");
    println!("你猜的数字是: {}", str);
}

注意

rust表达式必须要有分号

rust string类型必须是双引号

结尾

下一节:第三篇 猜数字游戏(2)

上一节:Rust从入门到跑路 - 第二篇 Hello Word