Rust 入门笔记

做个备份Rust案例猜数use std::io;use rand::Rng;use std::cmp::Ordering;fn main() { let mut guess = String::new(); let secret_number = rand::thread_rng().gen_range(1, 101); // 1-100 println!("{}", secret_number); loop { io::stdin().
摘要由CSDN通过智能技术生成

做个备份

Rust

案例

猜数

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

fn main() {
   
    let mut guess = String::new();
    let secret_number = rand::thread_rng().gen_range(1, 101);   // 1-100
    println!("{}", secret_number);
    loop {
   
        io::stdin().read_line(&mut guess).expect("cant read line");
        let guess: u32 = match guess.trim().parse() {
   
            Ok(num) => num,
            Err(_) => continue,
        };

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

变量

const MAX_P: u32 = 100_000;
fn main() {
   
    let x = 5;
    let x = x ** 5;
    println!("{}", x);

    let spaces = "   ";
    let spaces = spaces.len();
    println!("{}", spaces);
}

Tuple

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

    let (x, y, z) = tup;

    println!("{} {} {}", x, y, z);
    println!("{} {} {}", tup.0, tup.1, tup.2);
}

数组

fn main() {
   
    let a = [1, 2, 3, 4, 5];

    let months = [
        "one",
        "two",
    ];

    // 数组类型 [类型; 长度]
    let b: [i32; 5] = [1, 2, 3, 4, 5];

    // 如果数组中每个元素都相同
    // 相当于 let c = [3,3,3,3,3];
    let c = [3; 5];

    let one = months[0];
    let two = months[1];
}

函数

fn main() {
   
    another_function();
    other_function(5);

    let y = {
   
        let x = 1;
        x + 1
    };

    let five = five();
}

fn another_function() {
   
    println!("the value is 5");
}

fn other_function(x: i32) {
   
    println!("the value is {}", x);
}

fn five() -> i32 {
   
    5
}

条件判断

fn main() {
   
    let number = 5;
    if number < 5 {
   
        println!("less than 5");
    } else if number > 5 {
   
        println!("bigger than 5");
    } else {
   
        println!("equal 5");
    }

    // 这是因为 if 语句是一个表达式
    let condition = true;
    let number = if condition {
    5 } else {
    6 };
    println!("The value of number is: {}", number);
}

循环

fn main() {
   
    loop {
   
        println!("hello world");
    }

    let mut count = 0;
    let result = loop {
   
        count += 1;
        if count == 10 {
   
            break count * 2;
        }
    };
    println!("The result is {}", result);

    let mut number = 3;
    while number != 0 {
   
        println!("{}", number);
        number -= 1;
    }

    // 返回数组元素的迭代指针
    let a = [1, 2, 3, 4, 5];
    for element in a.iter() {
   
        println!("The value is {}", element);
    }

    // 左闭右开
    // rev() 能反转 range
    for number in (1 .. 4).rev() {
   
        println!("The value is {}", number);
    }
}

所有权

  • 所有权为了管理 heap 中的数据而生
  • 所有权解决的问题
    • 跟踪代码的哪些部分正在使用 heap 中的数据
    • 最小化 heap 上的重复数据量
    • 清理 heap 上未使用的数据以避免空间不足

所有权规则、内存与分配

String
  • 字符串字面量不能修改
  • String 类型的值可以修改
内存与分配
  • 字符串字面值,在编译时就知道她的内容了,其文本内容是可以直接硬编码到最终的可执行文件里

    • 速度快、高效
  • String 保存在 heap 中

  • Rust 中当某个值走出作用范围时,内存会立即自动交还给操作系统(通过自动调用 drop() 函数实现)

fn main() {
   
    let s1 = String::from("Hello");
    let s2 = s1;    //  于是 s1 失效了
    let s3 = s2.clone();    // 复制

    // 针对 stack 上的不存在 move 这一回事
    let x = 5;
    let y = x;
}
拥有 Copy Trait
  • 任何简单的标量的组合类型都可以是 Copy 的
  • 任何需要分配内存或某种资源的都不是 Copy 的
  • 一些拥有 Copy Trait 的类型
    • 所有的整数类型
    • bool
    • char
    • 所有的浮点类型
    • Tuple ,如果其所有的字段都是 Copy 的

所有权与函数

  • 在语义上,把值传递给函数和把值赋给变量是类似的
    • 将值传递给函数将发生移动或复制
  • 返回值与作用域
    • 函数在返回值的过程中同样也会发生所有权的转移
    • 一个变量的所有权总是遵循同样的模式
      • 把一个值赋给其他变量时就会发生移动
      • 当一个包含 Heap 数据的变量离开作用域时,它的值就会被 drop 函数清理,除非数据的所有权移动到另一个变量上
fn main() {
   
    let s = String::from("Hello World");
    take_ownership(s);

    let x = 5;
    makes_copy(x);

    println!("x: {}", x);
}

fn take_ownership(some_thing: String) {
   
    println!("{}", some_thing);
}

fn makes_copy(some_number: i32) {
   
    println!("{}", some_number);
}
fn main() {
   
    let s1 = gives_ownership();
    let s2 = String::from("hello");
    let s3 = takes_and_gives_back(s2);
}

fn gives_ownership() -> String {
   
    let some_string = String::from("hello");
    some_string
}

fn takes_and_gives_back(a_string: String) -> String {
   
    a_string
}
fn main() {
   
    let s1 = String::from("hello");
    let (s2, len) = calculate_length(s1);
}

fn calculate_length(s: String) -> (String, usize) {
   
    let length = s.len();

    (s, length)
}

引用与借用

  • 把某一个变量借用为不可变引用后,就不能把变量借用为可变引用

  • 引用允许使用某个值而不取得其所有权

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-plPRJxna-1639451769486)(/Users/chenghaijie/Library/Application Support/typora-user-images/image-20211203224800474.png)]

  • 不可以修改借用的东西

  • 和变量一样,引用默认是不可变的,但当创建的是可变引用时则可以修改它

  • 在特定作用域内,对某一块数据,只能有一个可变的引用

    • 这样做的好处是可在编译时防止数据竞争
fn main() {
   
    let s1 = String::from("Hello");
    let len = calculate_length(&s1);
    println!("The length of {} is {}", s1, len);
}

fn calculate_length(s: &String) -> usize {
   
    s.len()
}
fn main() {
   
    let mut s1 = String::from("Hello");
    let len = calculate_length(&mut s1);
    println!("The length of {} is {}", s1, len);
}

fn calculate_length(s: &mut String) -> usize {
   
    s.push_str(" world");
    s.len()
}

切片

  • 字符串字面值就是切片

  • 切片是不持有所有权的数据类型

fn main() {
   
    let mut s = String::from("Hello World");
    let worldIndex = first_world(&s);
    s.clear();
    println!("{}", worldIndex);
}

fn first_world(s: &String) -> usize {
   
    let bytes = s.as_bytes();

    // enumerate 会将迭代结果包装成元祖
    for (i, &item) in bytes.iter().enumerate() {
   
        if item == b' ' {
   
            return i;
        }
    }
    s.len()
}
  • 字符串切片是指向字符串中一部分内容的引用(左闭右开)

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YZRKcz00-1639451769487)(/Users/chenghaijie/Library/Application Support/typora-user-images/image-20211204085727364.png)]

    fn main() {
         
        let s = String::from("Hello World");
    
        let hello = &s[0..5];
        let world = &s[6..];
    
        let whole = &s[0..s.len()];
    }
    
  • 字符串字面值是不可变引用

  • 有经验的开发者通常会把函数参数以及返回值设置为 &str ,因为这样能接受不同类型的参数

    fn main() {
         
        let mut s = String::from("Hello World");
        let worldIndex = first_world(&s[..]);
    
        let my_s = "Hello World";
        let worldIndex = first_world(my_s);
    }
    
    fn first_world(s: &str) -> &str {
         
        let bytes = s.as_bytes();
    
        // enumerate 会将迭代结果包装成元祖
        for (i, &item) in bytes.iter().enumerate() {
         
            if item == b' ' {
         
                return &s[0..i];
            }
        }
        &s[0..]
    }
    
  • 其他类型的切片

    fn main() {
         
        let a = [1, 2, 3, 4, 5];
        let slice = &a[1..3]
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值