Rust 学习笔记(二)数据类型

#ProgrammingLanguage/Rust

可变变量

let mut x : u32 = 5;//mut表示是可变变量, :u32表示变量类型,可以不指定,采用默认值i32。

常量

const MAX_POINTS: u32 = 100_000;

shadowing

let x = 5; 
let x = x+1;
let x = x*2;

你可以声明一个与先前变量同名的新变量,并且该新变量会覆盖先前的变量。 虽然x是不可变变量,但是可以通过showing机制,进行重名变量初始化,达到类似可变变量的行为。

标量 (scalar)和复合变量(compound) 标量代表一个单一的值,rust有四个主要的标量类型:整型 浮点型 布尔型 字符型。

tuple : tuple是一种聚合不同类型参数到一个类型的类型。(可以理解为可以每个元素类型不同的特殊数组)

let tup: (i32, f64, u8) = (500, 6.4, 1);

可以通过解构方式将三个元素分开。

let tup = (500, 6.4, 1);
let (x, y, z) = tup;
println!("The value of y is: {}", y);

还有一种通过序号进行单独访问的办法,序号从0开始。

let x: (i32, f64, u8) = (500, 6.4, 1);
let five_hundred = x.0;
let six_point_four = x.1;
let one = x.2;

array: 数组中元素的类型必须是一致的。 这里需要特别注意的是,rust中的数组,长度一旦确定,就不能增长或者减短。

函数内的状态和申明:

let y = 6;//没有返回值,不能作为右值
let x = (let y = 6);//错误

表达式可以是语句的一部分:

let y = {
	let x = 3;
	x + 1
};
//最后y等于4,注意这个表达式block的最后一行没有分号!!!,如果有分号就是一个单纯的语句而已了。

注意区分 statement 和 expression

{
	let x = 3;
	x + 1
}//expression
{
	let x = 3;
	x + 1;
}//statement

函数的返回值可以在函数名的输入参数括号之后通过 - >来进行申明。 函数的返回值,必须是函数体最后的expression。

fn five() -> i32 { 
	5//没有分号
}
fn main() {
let x = five();
println!("The value of x is: {}", x); }
fn main() {
let x = plus_one(5);
println!("The value of x is: {}", x); }
fn plus_one(x: i32) -> i32 { 
	x + 1
}

if 表达式: 如果条件为true,则将条件放置在大括号中之后。第一分支为条件表达式为真的分支。

fn main() {
let number = 3;
if number < 5 { //这里和C有明显区别,没有用圆括号括住条件表达式
println!("condition was true");
} else {
println!("condition was false");
} }

比while更为安全的for语句:

let a = [10, 20, 30, 40, 50];
for element in a.iter() {//正向
	println!("The value is: {}", element);
}

for number in (1..4).rev() {//反向
	println!("{}!", number); 
}

⚠️注意一下这种写法是错误的

 fn main() {
     let a = [10,20,30,40,50];
     for element in a.rev() {
         println!("The value is {}" , element);
     }
 }
error[E0599]: no method named `rev` found for array `[{integer}; 5]` in the current scope
 --> src/main.rs:3:23
  |
3 |      for element in a.rev() {
  |                       ^^^ method not found in `[{integer}; 5]`
  |
  = note: the method `rev` exists but the following trait bounds were not satisfied:
          `[{integer}; 5]: std::iter::Iterator`
          which is required by `&mut [{integer}; 5]: std::iter::Iterator`
          `[{integer}]: std::iter::Iterator`
          which is required by `&mut [{integer}]: std::iter::Iterator`

error: aborting due to previous error

简单的介绍了几种数据类型,举一个例子来熟悉新的概念和知识。

[package]
name = "guessing_game" //project or lib name
version = "0.1.0"	//verison
authors = ["Your Name <you@example.com>"]
[dependencies] //export libs

fn main() { println!(“Guess the number!”);

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

let mut guess = String::new();

io::stdin() //调用标准io库的函数
    .read_line(&mut guess) //通过引用将,读到的值传入可修改变量guess
    .expect("Failed to read line");//如果读取失败,打印错误信息
println!("You guessed: {}", guess); }

* 引入外部库,产生随机数,修改项目根目录下的Cargo.toml文件

[dependencies] rand = “0.5.5”


然手在命令行执行
``` bash
$ cargo build
    Updating crates.io index
  Downloaded rand v0.5.5
  Downloaded libc v0.2.62
  Downloaded rand_core v0.2.2
  Downloaded rand_core v0.3.1
  Downloaded rand_core v0.4.2
   Compiling rand_core v0.4.2
   Compiling libc v0.2.62
   Compiling rand_core v0.3.1
   Compiling rand_core v0.2.2
   Compiling rand v0.5.5
   Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
    Finished dev [unoptimized + debuginfo] target(s) in 2.53s

在项目编译的时候,会自动下载外部carte。(PS:如果在国内使用建议使用镜像),顺道一提,Cargo.lock确保你在编译的时候,会根据你在Cargo.toml文件中指定的外部库的版本,进行编译,但是如果你想更新外部库到最新版本,可以执行 cargo update, 这个命令会忽略Cargo.lock,并下载最新的外部库。

fn main() { println!(“Guess the number!”);

  //因为 use rand::Rnd 的引入,可以通过 rand::调用第三方库的公开函数thread_rng()的一个子函数gen_range(),产生一个范围(1~101)之间的随机数
let secret_number = rand::thread_rng().gen_range(1, 101);

  //循环读取输入的猜测的数字,并和随机产生的目标数字进行比较
loop {
    println!("Please input your guess.");

    let mut guess = String::new();

	   //从标准输入输出,读取到一个字符串形式的数字
    io::stdin()
        .read_line(&mut guess)
        .expect("Failed to read line");

	  //将读取到的字符串,通过trim()去掉首尾的空格,再通过parsr()将字符串类型转换为无符号整型参数
    let guess: u32 = match guess.trim().parse() {
        Ok(num) => num,
        Err(_) => 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; //猜到正确数字,跳出循环
        }
    }
} }

⚠️ gen_range在下限包含但在上限不包含,因此我们需要指定1和101以请求1到100之间的数字。
如果你想查询更多cargo相关的说明,执行
``` rust
cargo doc --open

会在浏览器自动弹出帮助页面,会把你项目里面所有用到的库,在左侧列出,点击可以查看细节。