Rust猜数字之比较

比较

既然我们获得了用户的输入,让我们把猜测的数据跟神秘数字做比较。这是我们的下一步,尽管它还不能真正工作:

     extern crate rand;

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

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

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

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

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

         let mut guess = String::new();

         io::stdin().read_line(&mut guess)
             .ok()
             .expect("failed to read line");

         println!("You guessed: {}", guess);

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

一些新加入的内容。第一个是另外一个use。我们带来了一个新类型叫做std::cmp::Ordering。底部有5行使用它:

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

cmp()方法可以在任何可比较的东西上调用,它会使用你要比较的东西的一个引用。它将会返回我们前面使用的Ordering类型。我们使用match声明来决定确切的是那种Ordering。Ordering是一个枚举(enum),‘enumeration’的缩写,看起来是这样子的:

     enum Foo{
          Bar,
          Baz,
     }

有了这个定义,所有是Foo类型的不是Foo::Bar就是Foo::Baz。我们使用::来指明特定枚举变量的命名空间。

Ordering枚举类型有三种可能的变化:Less、Equal和Greater。match声明使用一种类型的值,并为每种可能的值创建一个分支‘arm’。因为我们有三种类型的Ordering,我们有三种分支(arms):

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

如果是Less,我们打印Too small!,如果是Greater,打印Too big!,如果是Equal,打印You win!。match很有用,在Rust中经常用到。

我提到过这个程序不能工作。让我们试一下:

     $ cargo build
        Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
     src/main.rs:28:21: 28:35 error: mismatched types:
     expected `&collections::string::String`,
         found `&_`
     (expected struct `collections::string::String`,
         found integral variable) [E0308]
     src/main.rs:28     match guess.cmp(&secret_number) {
                                        ^~~~~~~~~~~~~~
     error: aborting due to previous error
     Could not compile `guessing_game`.

这是一个严重的错误。主要的愿意是我们有‘不匹配的类型’。Rust有一个强、静态类型系统。然而,它有类型推断功能。当我们写let guess = String::new()时,Rust能够推断出guess是一个String类型,所以它没有要求我们写出类型。对于我们的secret_number,有一些类型可以有1-100之间的值:i32,一个32位的数,或者u32,一个无符号32位数,或i64,一个64位数。或者其它的。迄今为止,这都不是问题,Rust默认是一个i32.然而,在这里,Rust不知道怎么比较guess和secret_number。他们需要是相同的类型。最终,我们想将我们读取到的String转换成一个真正的数字类型。我们可以通过额外的三行代码实现。这是我们的新程序:

     extern crate rand;

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

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

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

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

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

         let mut guess = String::new();

         io::stdin().read_line(&mut guess)
             .ok()
             .expect("failed to read line");

         let guess: u32 = guess.trim().parse()
             .ok()
             .expect("Please type a number!");

         println!("You guessed: {}", guess);

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

新的3行是:

      let guess: u32 = guess.trim().parse()
             .ok()
             .expect("Please type a number!");

等一下,我们不是已经有一个guess了吗?我们确实有了,但是Rust允许我们使用一个新的隐藏(shadow)先前的。在这种情况下经常使用,当guess以String开始,但是我们想将其转换成一个u32类型的数据。隐藏技术允许我们重用guees名字,而不是强制我们想出两个不一样的名字,例如guess_str和guess,或者其它的。

我们将guess绑定到一个与我们先前看起来有些相像的表达式上:

     guess.trim().parse()

跟随着一个ok().expect()调用。这里guess指的是老guess,也就是保存我们输入的那个String。String上的trim()方法将会消除字符串开头和结尾的所有空白字符。这个很重要,因为我们要满足read_line()必须按下回车键(return)。这意味着如果我们输入5并敲击回车键,guess看起来将会这样:5\n。\n代表换行(newline),输入(enter)键。trim()去掉它,留下我们的字符串仅仅包含5。字符串上的的parse()方法将字符串解析成某种类型的数字。因为它可以解析多种数字,我们需要给Rust一个暗示,来获取我们想要的数字的类型。因此,let
guess: u32。guess后面的冒号(:)告诉Rust我们将阐明它的类型。u32是一个无符号、32位整数。Rust有一些内建数字类型,但是我们已经选择u32.对于一个小正整数这是一个很好的默认选择。

跟read_line()一样。我们的对parse()的调用会产生一个错误。如果我们的字符串包含A%将会怎样?将没有方法将其转换成数字。同样,我们将会跟read_line()一样做同样的事情:如果有错误发生,使用ok()和expect()方法使程序崩溃。

让我们试一下程序!

     $ cargo run
        Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game)
          Running `target/guessing_game`
     Guess the number!
     The secret number is: 58
     Please input your guess.
       76
     You guessed: 76
     Too big!

非常好!你可以看到我输入的空格,但是他依旧会指出我猜的是76。多运行几次程序,验证猜数字程序正常工作。

现在我们可以是程序的大部分工作,但是我们只能裁一次。让我们使用循环改改它!

时间: 2024-11-02 23:41:14

Rust猜数字之比较的相关文章

Rust猜数字之循环

循环 loop关键字给我们一个无限循环.让我们添加它: extern crate rand; use std::io; use std::cmp::Ordering; use rand::Rng; fn main() { println!("Guess the number!"); let secret_number = rand::thread_rng().gen_range(1, 101); println!("The secret number is: {}"

Rust猜数字之产生神秘数字

产生一个神秘数字 接下来,我们需要产生一个神秘数字.Rust在它的标准库中还没有包括随机数函数.然而,Rust团队确实提供了一个一个rand crate.'crate'是Rust代码的一个包.我们已经构建了一个二进制crate,是可执行的.rand是一个库crate'library crate',包括可以被其他程序使用的代码. 使用外部crate是Cargo真正的闪光点.在我们可以使用rand写代码之前,我们需要修改我们的Cargo.toml.打开该文件,并在底部添加下列代码: [depende

20170913自制猜数字游戏

/* 猜数字:系统随机生成一个四位数,请根据下列判断猜出来 A:数值正确,位置正确 B:数值正确,位置不正确 C:数值不正确 */ #include<stdio.h> #include<time.h> #include<stdlib.h> #pragma warning (disable:4996) #define pUCharHead unsigned char * //以数组形式返回n个无重复的随机数,范围可指定[min,max] pUCharHead GenNoR

JavaScript一个猜数字游戏

效果图: 代码: <body> <script type="text/javascript"> window.onload = newgame; //页面载入的时候就开始一个新的游戏 window.onpopstate = popState; //处理历史记录相关事件 var state,ui; //全局变量,在newgame()方法中会对其初始化 function newgame( playagin ){ //开始一个新的猜数字游戏 //初始化一个包含需要的文

函数调用_猜数字和简易计算器

package app1; import java.util.*; public class TestFunction{     public static void main(String[] args){         Scanner sc=new Scanner(System.in);         System.out.print("请选择一项应用:\n1.猜数字\n2.简易计算器");         int n=sc.nextInt();         switch(

【bzoj入门】3189 猜数字(数学,搜索)

Description 味味最近在玩猜数字的游戏,现在她也希望你来玩一下这个游戏.猜数字游戏的规则是这样的,告诉你一个正整数 n(2<=n<=11),然后味味心中会想一个 n 个数字组成的数字串 (数字串最前面若干位可能是 0).味味会随意排列 n 位数上的数字,这样可能产生 n!个 n 位数.(n!=1×2×3×4×5×......×n,n!念作"n 阶乘").比如味味想了一个三位数 abc,那么一共会产生六个三位数,分别为 abc,acb,bac,bca,cab,cba

猜数字游戏及rand()函数

#include<stdio.h>#include<stdlib.h>int main() { short number; short guess=0; number=rand()%100; number++; printf("猜数字游戏\n"); printf("该数字在1到100之间\n"); while(guess!=number) { printf("请你输入所猜数字:"); scanf("%hd&quo

简单的猜数字小游戏

/** 简单的猜数字小游戏 要求如下: 用户输入想猜测数字的范围,输入1000则是0~1000之内的数字,程序就会内置一个 1 到 1000 之间的数字作为猜测的结果,由用户猜测此数字,用户每猜测一次,由系统提示猜测结果:大了.小了或者猜对了:直到用户猜对结果,则提示游戏结束.用户可以提前退出游戏,即,游戏过程中,如果用户录入数字0则游戏终止.加入新功能: 记次猜测次数功能,提示游戏开始时间,计猜测总用时功能,提示游戏结束时间 思路:1.用户输入电脑生成的数值取值范围,接收并判断是否是合理数值?

猜数字-暴力枚举

A - 猜数字 Time Limit:10000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status id=17473" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" style="display:inline-block; position:rela