【Rust】第四节:通用编程概念

发布时间:2023年12月18日

0 前言

本节内容比较多,但也比较容易理解
主要包括:变量和可变性、数据类型、函数、注释、控制流
就不分成三章了,一篇讲完,每一部分
原文:Rust 程序设计语言


1 变量和可变性、数据类型

1.1 代码

fn main() {
    //
    // 3.1 变量和可变性
    //
    // 基本类型
    let a = 1; // 变量(不可变)
    let mut b = 2; // 变量(可变)
    const THREE_HOURS_IN_SECONDS: u32 = 60 * 60 * 3; // 常量

    // 遮蔽
    let x = 5;
    let x = x + 1; // 遮蔽(shadow)
    {
        let x = x * 2;
        println!("The value of x in the inner scope is : {}", x); 
    }
    println!("The value of x is: {}", x);

    // 不可遮蔽
    // let mut x1 = 5; 
    // let x1 = x1 + 1; // 非法的遮蔽

    let mut y = 6; // 变量(可变)
    y = y + 1;
    println!("The value of y is : {}", y);

    // 变量类型不可变
    // let mut spaces = "    ";
    // spaces = paces.len(); // 不允许修改变量的类型

    // 遮蔽类型可变
    let spaces1 = "    ";
    let spaces1 = spaces1.len();
    println!("the value of spaces1 is {}", spaces1);

    //
    // 3.2 数据类型(静态类型)
    //
    // 3.2.1 标量类型(整型、浮点型、布尔型、字符)
    // 整型
    let no_guess = 42 // 不需要显式声明的整型
    let guess: u32 = "42".parse().expect("Not a number!"); // 需要显式声明的整型
    // 浮点型
    let x = 2.0; // f64
    let y: f32 = 3.0; // f32
    // 布尔型
    let t = true;
    let f: bool = false; 
    // 字符类型(char,不是字符串)
    let c = 'z';
    let z = '?';
    let heart_eyed_cat = '😻';

    // 3.2.2 复合类型(元组类型、数组类型)
    // 元组类型
    // 解构取值
    let tup = (500, 6.4, 1);
    let (x, y, z) = tup;
    let x: (i32, f64, u8) = (500, 6.4, 1);
    // .取值
    let tup: (i32, f64, u8) = (500, 6.4, 1);
    let five_hundred = x.0;
    let six_point_four = x.1;
    let one = x.2;
    // 数组类型
    let months = ["January", "February", "March", "April", "May", "June", "July",
              "August", "September", "October", "November", "December"];
    let a: [i32; 5] = [1, 2, 3, 4, 5];
    let a = [3; 5];
}

1.2 重点

1.2.1 变量和可变性

1、变量,默认是不可变的不能二次赋值,但你也可以选择让他可变,只要添加mut,但数据类型不可变
2、常量,是不允许更改的值,与其他语言相似。
3、遮蔽,可以通过声明和前面变量有相同名字的变量来遮蔽前面的变量。
注意:a、不能遮蔽可变的变量,b、遮蔽后的新变量仍应是一个不可变的变量,c、遮蔽后的新变量可以与前一个变量拥有不同的数据类型

1.2.2 数据类型

1、Rust是静态类型,必须在编译阶段能够确定出变量的类型。
2、标量类型:整型、浮点型、布尔型、字型;复合类型:元组、数组。
3、整型,数字字面量可以使用_作为可视分隔符方便读书,类似1_000
4、整型,要当心整型溢出。
5、数字运算,整数除法会向下取整。
6、字符,用''括起来,与字符串不同,大小为4个字节,是一个unicode标量值,所以可表示的远不止ASCII。
7、元组,每个位置类型可以不同。
8、元组,可以通过解构、.来进行取值。
9、元组,没有任何值的元组()被称为单元类型,值被称为单元值,表达式无返回值会隐式返回单元值,后面“2函数”部分也会提到。
10、数组,数组每个元素必须具有相同类型。
11、数组,与其他语言不通,长度是固定的
12、数组,长度可变的是vector,向量,也被称为“动态数组、可变数组”。
13、数组,访问时发生越界会导致运行时错误,程序直接退出。

1.3 其他

1、字符的概念,会在后文展开。
2、vector,会在后文展开。


2 函数、注释

2.1 代码

fn main() {
    // 函数:参数
    another_function(5);
    print_labeled_measurement(5, 'h');

    // 语句与表达式
    // let x = (let y = 6); // 不能用语句给语句赋值,要用表达式给语句赋值
    let y = {
        let x = 3;
        x + 1 // 没有分号
    };
    println!("The value of y is: {}", y);

    // 函数:返回值
    let x = five();
    println!("The value of x is: {}", x);

    // 函数:参数、返回值
    let x = plus_one(5);
    println!("The value of x is: {}", x);
}
// 函数:单参数
fn another_function(x: i32) {
    println!("The value of x is: {}", x);
}
// 函数:多参数
fn print_labeled_measurement(value: i32, unit_label: char) {
    println!("The measurement is: {}{}", value, unit_label);
}
// 函数:返回值
fn five() -> i32 {
    5
}
// 函数:参数、返回值
fn plus_one(x: i32) -> i32 {
    x + 1 // 如果在末尾加上';'无返回值,则返回单元类型‘()’,会产生错误
}

2.2 重点

2.2.1 函数

1、代码风格,函数、变量名采用下划线命名法规范风格。
2、函数,可以定义在main之前或之后都可以。
3、函数,使用参数需要明确数据类型。
4、语句,是没有返回值的,一般以;结尾。
5、表达式,是有返回值的,一般没有;结尾。
6、函数,以表达式方式添加返回值,且需要明确返回值的数据类型。
7、函数,返回值与接收返回值的变量的数据类型需要一致。

2.2.2 注释

1、代码中请使用//
2、文档注释使用///,但一般并不使用。
3、编译器不会报错,但请不要使用/** */

2.3 其他

暂无补充


3 控制流

3.1 代码

fn main() {
    //
    // 条件 if
    //
    // if
    let number = 3;
    if number < 5 {
        println!("condition was true");
    } else {
        println!("condition was false");
    }

    // if 类型需要严格匹配
    // if number {
    //    println!("number was three");
    // }

    // if 与 let
    let condition = true;
    let number = if condition { 5 } else { 6 }; // 返回值,需要是同样类型
    // let number = if condition { 5 } else { "six" }; // 返回值,不能是不同类型
    println!("The value of number is: {}", number);


    //
    // 循环 loop、while、for
    //
    // loop
    // loop 退出方式
    let mut count = 0;
    'counting_up: loop { // 标签counting_up
        println!("count = {}", count);
        let mut remaining = 10;
        loop {
            println!("remaining = {}", remaining);
            if remaining == 9 {
                break; // 退出内层循环 remaining
            }
            if count == 2 {
                break 'counting_up; // 退出外层循环 count,标签counting_up
            }
            remaining -= 1;
        }
        count += 1;
    }
    println!("End count = {}", count);
    // loop 退出并返回值
    let mut counter = 0;
    let result = loop {
        counter += 1;

        if counter == 10 {
            break counter * 2;
        }
    };
    println!("The result is {}", result);
    // while
    // 容易出现数组越界问题
    let a = [10, 20, 30, 40, 50];
    let mut index = 0;
    while index < 5 {
        println!("the value is: {}", a[index]);
        index += 1;
    }
    // for
    // 相对安全、简洁
    let a = [10, 20, 30, 40, 50];
    for element in a {
        println!("the value is: {}", element);
    }
    // for 例子2,rev是反转区间函数
    for number in (1..4).rev() {
        println!("{}!", number);
    }
    println!("LIFTOFF!!!");
}

3.2 重点

1、if需要判断的是bool值,与其他语言不同,不会将number转化为bool类型来判断。
2、if可以与let语句结合使用,只要if表达式能够正确地返回值,并且ifelse的返回值必须是同样的数据类型。
3、loop需要break来跳出循环,一般只会跳出内层循环,也可以指定跳出一个循环标签
4、while可以减少loop的嵌套。
5、for对集合进行遍历比while跟安全简洁。

3.3 其他

暂无补充


4 其他

下一章即将进入“所有权”这个Rust独有的概念。

文章来源:https://blog.csdn.net/RogerQianpeng/article/details/134996219
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。