书里是第2章内容,不过我在看完前11章后,才回过头来看。

02.1 原始代码

书里的代码是比较简单的:

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

fn main() {
    println!("Guess the number!");

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

    println!("The secret number is: {secret_number}");

    loop{
        println!("Please input your guess.");

        let mut guess = String::new();
        io::stdin().read_line(&mut guess)
            .expect("Failed to read line");

        let guess: u32 = match guess.trim().parse::<u32>() {
            Ok(num) => num,
            Err(_) => {
                println!("Please type a number!");
                continue;
            }
        };

        println!("You guessed: {guess}");
        match guess.cmp(&secret_number) {
            Ordering::Less => println!("Too small"),
            Ordering::Greater => println!("Too big!"),
            Ordering::Equal => {
                println!("You win!");
                break;
            }
        }
    }

}

虽然比较简单,还是有些要避坑的注意点:

  1. 与书上不太一样, match str.parse() 是不行的,因为parse 返回没有指定类型,需要使用parse::<u32> 明确类型
  2. match 对应的匹配符号是 =>,我写成了 :,找问题时还反应不过来,找了半天才找到。
  3. 使用rand模块时,从镜像拉取库失败,最后安装了一个 crm,使用官方镜像才成功。
  4. 生成随机数时, gen_range(1..=100) 意思是从1100,包含100 ,如果没有=意思是不包括100

02.2 优化

作为一名成熟的程序员,已经学了后面几章,当然不满足于此。

封装guess模块和 Guess结构:

// guess.rs
use std::cmp::Ordering;
use std::fmt;

#[derive(Debug)]
pub struct Guess{
    value: u32,
}

impl Guess{
    pub fn new(v: u32)-> Result<Guess, String>{
        if v < 1 || v > 100 {
            Err("Invalid input value, please input value between 1 and 100!".to_string())
        } else {
            Ok(Guess{value: v})
        }
    }

    pub fn from_str(v: &str) -> Result<Guess, String>{
        let value = match v.trim().parse::<u32>() {
            Ok(value) => value,
            Err(_) => return Err("Please type a number!".to_string())
        };

        Self::new(value)
    }


    pub fn cmp(&self, secret_num: u32) -> Ordering {
        return self.value.cmp(&secret_num)
    }

    pub fn check(&self, secret_num: u32) -> Result<String, String> {
        match self.cmp(secret_num) {
            Ordering::Less => Err("Too small".to_string()),
            Ordering::Greater => Err("Too big!".to_string()),
            Ordering::Equal => Ok("You win!".to_string()),
        }
    }
}

impl fmt::Display for Guess{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result{
        write!(f, "Your guess is: {}", self.value)
    }
}

main改为调用模块:

use std::io;
use rand::Rng;
mod guess;

use guess::Guess;

fn main() {
    println!("Guess the number!");

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

    println!("The secret number is: {secret_number}");

    loop{
        println!("Please input your guess.");

        let mut guess = String::new();
        io::stdin().read_line(&mut guess)
            .expect("Failed to read line");

        let guess = match Guess::from_str(&guess) {
            Ok(guess) => guess,
            Err(msg) => {
                println!("{}", &msg);
                continue;
            }
        };

        println!("{}", guess);
        match guess.check(secret_number) {
            Err(msg) => println!("{msg}"),
            Ok(msg) => {
                println!("{msg}");
                break;
            }
        }
    }

}

基本将之前能使用的技术都用了一遍。
模块、traitResult等。

  • 打赏
  • 分享
分享到...
请选择打赏方式
  • 微信
  • 支付宝

By yhl

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注