Rust Vec索引越界

起因

在前几天,在把C++刷题改为Rust的时候,遇到Vec下标越界的问题,主要是Rust for和C++/C#不太一样,当时在改为Rust代码的时候,粗暴的把for改为while,改好之后,就没对代码验证(很自信,然后就很打脸).

有问题的代码

pub fn move_zeroes(nums: &mut Vec<i32>) {
    let total: usize = nums.len();
    let mut new_vec: Vec<i32> = Vec::new();
    let mut index: usize = 0;
    while index < total {
        if nums[index] != 0 {
            new_vec.push(nums[index]);
        }
        index += 1;
    }

    let mut i: usize = 0;
    while i < index {  //这里使用index,本意是index是vec的长度,实际上index是nums的长度,index比new_vec的size大
        nums[i] = new_vec[i];
        i += 1;
    }

    while i < total {
        nums[index] = 0;  //这里使用index,会造成越界
        index += 1;       
    }
}

由于判断条件,有问题,造成new_vec下标越界

没问题的代码

pub fn move_zeroes(nums: &mut Vec<i32>) {
    let total: usize = nums.len();
    let mut new_vec: Vec<i32> = Vec::new();
    let mut index: usize = 0;
    while index < total {
        if nums[index] != 0 {
            new_vec.push(nums[index]);
        }
        index += 1;
    }

    let mut i: usize = 0;
    while i < new_vec.len() {  //这里使用index,本意是index是vec的长度,实际上index是nums的长度,index比new_vec长度大,造成下标越界
        nums[i] = new_vec[i];
        i += 1;
    }

    while i < total {
        nums[i] = 0;
        i += 1;
    }
}

使用for更优雅的,实现访问下标和访问元素

pub fn move_zeroes(nums: &mut Vec<i32>) {
    let total: usize = nums.len();
    let mut new_vec: Vec<i32> = Vec::new();
    //for 通过下标,也用自己 +=1
    for index in 0..total {
        if nums[index]!=0 {
            new_vec.push(nums[index]);
        }
    }

    //在Rust 使用for 也可以有下标,直接访问当前索引执行的元素
    for (i, item) in new_vec.iter().enumerate() {
        nums[i] = *item;
    }

    for index in new_vec.len()..total {
        nums[index] = 0;
    }
}
秋风 2021-06-06