# [Rust]49道例题

> [[Rust]49道例题](https://www.ftls.xyz/posts/rust40/)
> Penned by [恐咖兵糖](https://www.ftls.xyz/) on 2021-09-23


这是我学习Rust路上的做的习题集

<!--more-->

题目和部分解答来源: http://www.codebaoku.com/rust-example/rust-example-index.html

说明: 这是我学习Rust路上的做的习题集，记下的笔记。题目内容非常基础。部分题目我懒得写了，有些也没按要求写，见谅。

[toc]
## 1.数字组合
**Rust语言编程题目**：有1、2、3、4个数字，能组成多少个互不相同且无重复数字的三位数？都是多少？<br />**程序分析**:可填在百位、十位、个位的数字都是1、2、3、4。组成所有的排列后再去 掉不满足条件的排列。（三重循环）<br />源代码如下:
```rust
fn main() {
    let mut sum=0;
    for x in 1..5 {
        for y in 1..5 {
            for z in 1..5 {
                if x!=y && y!=z && x!=z {
                    sum += 1;
                }
            }
        }
    }
    println!("{}", sum);
}
// 模拟
```
## 2.判断语句
**Rust语言编程题目**：企业发放的奖金根据利润提成。

- 利润(I)低于或等于10万元时，奖金可提10%；
- 利润高于10万元，低于20万元时，低于10万元的部分按10%提成，高于10万元的部分，可提成7.5%；
- 20万到40万之间时，高于20万元的部分，可提成5%；
- 40万到60万之间时高于40万元的部分，可提成3%；
- 60万到100万之间时，高于60万元的部分，可提成1.5%；
- 高于100万元时，超过100万元的部分按1%提成。

从键盘输入当月利润I，求应发放奖金总数？<br />**程序分析**:请利用数轴来分界，定位。注意定义时需把奖金定义成长整型。<br />**知识点**:if条件判断，数据运算
```rust
fn main() {
    let mut input_data  = String::new();
    std::io::stdin().read_line(&mut input_data).expect("read_line failed!");
    match input_data.trim().parse::<i32>() {
        Ok(data) => {
            match data {
                0..=10_0000 => println!("{}",f64::from(data)*0.1),
                10_0001..=20_0000 => println!("{}",10.0*0.1+(f64::from(data-10))*0.75), //
                20_0001..=40_0000 => println!("3ok"),
                40_0001..=60_0000 => println!(""),
                60_0001..=100_0000 => println!(""),
                _ => println!("{}", data)
            }
        }
        Err(_err) => {println!("{}",_err); }
    }
}
// 模拟 知识点 : match
```
## 3.循环语句
**Rust语言编程题目**：一个整数，它加上100后是一个完全平方数，再加上168又是一个完全平方数，请问该数是多少？<br />**程序分析**:<br />假设该数为 x。<br />1、则:x + 100 = n2, x + 100 + 168 = m2<br />2、计算等式:m2 - n2 = (m + n)(m - n) = 168<br />3、设置: m + n = i，m - n = j，i * j =168，i 和 j 至少一个是偶数<br />4、可得: m = (i + j) / 2， n = (i - j) / 2，i 和 j 要么都是偶数，要么都是奇数。<br />5、从 3 和 4 推导可知道，i 与 j 均是大于等于 2 的偶数。<br />6、由于 i * j = 168， j>=2，则 **1 < i < 168 / 2 + 1**。<br />7、接下来将 i 的所有数字循环计算即可。<br />**知识点**:if条件判断，while循环
```rust
fn main() {
    for a in 1..168 {
        for b in 1..168 {
            if b*b+2*a*b == 168 { println!("{}", a*a-100)}
        }
    }
}
// x + 100 = a^2
// y + 268 = (a+b)^2
// 168 = a^2+2*a*b 
// 暴力
```
## 4.日期判断
**Rust语言编程题目**：输入某年某月某日，判断这一天是这一年的第几天？<br />**程序分析**:以4月8日为例，应该先把前三个月的加起来，然后再加上8天即本年的第几天，如果遇到特殊情况，闰年且输入月份大于等于3时需考虑多加一天。下面的解法仅仅是为了练习知识点而得出的参考答案，当然还有其它的解答方法。大家也可以试一下。<br />**知识点**:错误校验，条件判断，字符串分割，动态数组
```rust
fn main() {
    println!("Please input YYYYMMDD");
    let arr:[i32;12]=[31,28,31,30,31,30,31,31,30,31,30,31];
    let mut input_data  = String::new();
    std::io::stdin().read_line(&mut input_data).expect("read_line failed!");
    let year_time= input_data[0..4].trim().parse::<i32>();
    let monther_time= input_data[4..6].trim().parse::<i32>();
    let day_time= input_data[6..8].trim().parse::<i32>();
    // println!("{:?} {:?} {:?}",year_time,monther_time,day_time);
    let mut ans = 0;
    if let Ok(key) = monther_time { 
        if monther_time.unwrap()>=2 {
            for iner in 0..(key-1)as usize { ans += arr[iner]; }
            if key>2&&is_leap_year(year_time.unwrap()) { ans+=1; }
        }
    }
    println!("{}",ans+day_time.unwrap());
}
fn is_leap_year(year:i32) -> bool {
    if year % 400 == 0 { true }
    else {
        if year%4==0&&year%100!=0 { true } else { false }
    }
}
// 先判断闰年 然后加日期
```
## 5.数字排序
**Rust语言编程题目**：输入三个整数x,y,z，请把这三个数由小到大输出。<br />**程序分析**:我们想办法把最小的数放到x上，先将x与y进行比较，如果x>y则将x与y的值进行交换，然后再用x与z进行比较，如果x>z则将x与z的值进行交换，这样能使x最小。基础练习，不要使用Vec。<br />**知识点**:运算符 let match<br />​<br />
```rust
fn main() {
    let mut input = String::new();
    std::io::stdin().read_line(&mut input).expect("Fail to read line");
    let mut s = input.split_whitespace();
    let mut a:i32 = s.next().unwrap().parse().unwrap();
    let mut b:i32 = s.next().unwrap().parse().unwrap();
    let mut c:i32 = s.next().unwrap().parse().unwrap();
    // let a: i32 = s.next().unwrap().parse().unwrap();
    // let a = s.next().unwrap(); // a 是 str
    order(&mut a,&mut b);
    order(&mut a,&mut c);
    order(&mut b,&mut c);
    println!("{} {} {}", a, b,c);
}
fn order(a: &mut i32, b:&mut i32) {
    if a> b {
        std::mem::swap(a, b)
    }
}
// 笔记: 处理空格，排序，交换两个变量位置
```
## 6.打印图案
**题目**:请使用*号输出英文字母C的图案，类似于电子手表屏幕上的C。请使用两种方式实现。<br />**程序分析**:这个题目比较简单，可以先用'*'号在纸上写出字母C，再分行输出。第一种方式就是直接使用println打印输出了。第二种方式可以考虑使用循环来实现。<br />**知识点**: 循环 println
```rust
fn main() {
    let arr:[i32;4]=[5,1,1,5];
    for i in 0..4 {
        for _j in 0..arr[i] { print!("*"); }
        print!("\n");
    }
}
```
## 7.输出特殊图案
**题目**:请使用两种方式输出下面的特殊图案，请在rust环境中运行，看一看，Very Beautiful!<br />PS:该题源自于C语言，由于C语言字符是支持ASCII码，而Rust支持Unicode。因此创作此题。<br />提示:上图中的白色符号是**重四个气球形轮辐星号** ，其Unicode码是U+2724。红色符号是**沉重的黑心**，其Unicode码是U+2764。上图是在Windows PowerShell中运行的结果。<br />PS:不要在CMD中运行，你会看不到你想要的结果。<br />**程序分析**:Unicode字符有非常多。不同字符，图形不一样。按照字符输出即可。<br />**知识点**:声明字符 ，循环<br />输出:
```
❤✤✤✤❤
✤❤✤❤✤
✤✤❤✤✤
✤❤✤❤✤
❤✤✤✤❤
```
```rust
fn main()
{
    let a = '✤';
    let b = '❤';
    // let a: char = '\u{2724}';
    // let b: char = '\u{2764}';
    for i in 0..5{
        for j in 0..5 {
            if i==j || i+j+1 ==5 { print!("{}",b) }else { print!("{}",a)}
        }
        print!("\n");
    }
}
```
## 8.乘法口诀
**题目**:乘法口诀（也叫“九九歌”）在我国很早就已产生。远在春秋战国时代，九九歌就已经广泛地被人们利用着。常用的乘法口诀有两种，一种是45句的，通常称为小九九；还有一种是81句的，通常称为大九九。你能用Rust输出9_**9乘法口诀**_（小九九）吗。输出时格式要对齐。<br />**程序分析**:可以考虑分行与列，总共 9 行 9 列，i 控制行，j 控制列。使用制表符\t分隔。<br />**知识点**:循环
```rust
fn main() {
    for i in 1..10 {
        for j in 1..i {
            print!("{}*{}={}\t", j, i, i*j);
        }
        println!();
    }
}
```
## 9.国际象棋
**题目**:国际象棋（Chess），又称西洋棋，是一种二人对弈的棋类游戏。棋盘为正方形，由64个黑白（深色与浅色）相间的格子组成；棋子分黑白（深色与浅色）两方共32枚，每方各16枚。虽然汉语称之为西洋棋或国际象棋，但是实际上它起源于亚洲，后由阿拉伯人传入欧洲，成为国际通行棋种，也是一项智力竞技运动，曾一度被列为奥林匹克运动会正式比赛项目。你能输出国际象棋棋盘吗。提示:白块的Unicode字符是\u+25a0，黑块的Unicode字符是\u+25a1。<br />**程序分析**:国际象棋棋盘由64个黑白相间的格子组成，分为8行*8列。用i控制行，j来控制列，根据i+j的和的变化来控制输出黑方格，还是白方格。<br />**知识点**:循环
```rust
fn main() {
    let a = '\u{25a0}';
    let b = '\u{25a1}';
    for i in 0..8 {
        for j in 0..8 {
            if (i+j)%2==0 {print!("{}",a)} else {print!("{}",b)}
        }
        println!();
    }
}
```
## 10.打印楼梯足球
**题目**:现在人们的生活水平逐步提高，越来越多的人住进了楼房。楼房中必须存在的那就是楼梯了。现在有个需求，要求你打印一个有6个台阶的楼梯，同时从上向下数，在楼梯的第4节台阶有个足球。<br />提示:台阶使用Unicode字符\u+2591表示，足球的Unicode字符是\u+26bd。<br />**程序分析**:用i控制行，j来控制列，j根据i的变化来控制输出的方格（台阶）的个数。从上向下数第4节台阶有个足球，说明是在第三行打印足球。<br />**知识点**:循环，字符
```rust
fn main() {
    let a = '\u{2591}'; // stairs
    let b = '\u{26bd}'; // bolls
    for i in 0..6 {
        for j in 0..i+1 {
            print!("{}",a);
        }
        if i==3 { print!("{}",b); }
        println!();
    }
}
```
## 11.兔子生崽
**题目**:古典问题（兔子生崽）:有一对兔子，从出生后第3个月起每个月都生一对兔子，小兔子长到第三个月后每个月又生一对兔子，假如兔子都不死，问每个月的兔子总数为多少？（输出前40个月即可）<br />**输出格式**:每行4个数，共10行。<br />**程序分析**:兔子的规律为数列1,1,2,3,5,8,13,21....，即下个月是上两个月之和（从第三个月开始）。<br />**知识点**:循环，字符
```rust
fn main() {
    let mut vec = vec![1,1];
    for i in 2..41 {
        vec.push(vec[i-1]+vec[i-2]);
    }
    let mut sum = 0;
    for i in 0..40 {
        print!("{}\t", vec[i]);
        sum+=1;
        if sum==4 { println!();sum=0; }
    }
}
```
## 12.质数判断
**题目**:质数又称素数。一个大于1的自然数，除了1和它自身外，不能被其他自然数整除的数叫做质数。判断101到200之间的质数。<br />**输出格式**:每行只有5个数，总共输出5行，注意数据对齐。<br />**程序分析**:判断质数的方法:用一个数分别去除以2到N(这个数)，如果能被整除， 则表明此数不是质数，反之是质数。<br />**知识点**:循环
```rust
fn main() {
    let mut k = 0;
    for i in 101..=200 {
        if is_prime(i) { 
            print!("{}\t", i);
            k+=1;
            if k==5 { print!("\n");k=0; }
        }
    }
}
fn is_prime(number: i64) -> bool {  // 判断是否是素数
    for i in 2..(number / 2 + 1) {
        if number % i == 0 {
            return false;
        }
    }
    true
}
```
## 13.水仙花数
**Rust语言编程题目**：经典水仙花数问题。打印出所有的"水仙花数"，所谓"水仙花数"是指一个三位数，其各位数字立方和等于该数 本身。例如:153是一个"水仙花数"，因为153=1的三次方＋5的三次方＋3的三次方。<br />**程序分析**:利用for循环控制100-999个数，每个数分解出个位，十位，百位。<br />**输出格式**:每个数占一行。<br />**知识点**:循环
```rust
fn main() {
    for i in 100..1000 {
        let x = i/100;
        let y = (i/10)%10;
        let z = i%10;
        if x*x*x+y*y*y+z*z*z==i { println!("{}{}{}", x, y, z)}
    }
}
// 暴力
```
## 14.分解因子
**Rust语言编程题目**：将一个正整数分解质因数。例如:输入90,打印出90=2*3*3*5。输出136的质因数。<br />**程序分析**:对n进行分解质因数，应先找到一个最小的质数k，然后按下述步骤完成:

- 如果这个质数恰等于（小于的时候，继续执行循环）n，则说明分解质因数的过程已经结束，另外 打印出即可。
- 但n能被k整除，则应打印出k的值，并用n除以k的商,作为新的正整数n.重复执行第二步。
- 如果n不能被k整除，则用k+1作为k的值,重复执行第一步。

**输出格式**:输出一行。<br />**知识点**:循环
```rust
fn main() {
    let mut input: i64 = 136;
    let mut last = 0;
    print!("{}=", input);
    loop {
        
        for i in 2..input {
            if input%i==0&&is_prime(i) { print!{"{}*", i};input=input/i;break;}
            // if is_prime(input) { print!{"{}",input};break;}
        }
        if input==last { break; }
        last = input;
    }
    print!("{}", last);
}
fn is_prime(number: i64) -> bool {  // 判断是否是素数
    for i in 2..(number / 2 + 1) {
        if number % i == 0 {
            return false;
        }
    }
    true
}
```
## 15.条件运算
**Rust语言编程题目**：利用条件运算表达式来完成此题:学习成绩>=90分的同学用A表示，60-89分之间的用B表示，60分以下的用C表示。<br />**程序分析**:使用if-else当做表达式，然后赋值给某个变量，这是Rust条件运算符基本例子。<br />**输出格式**:不需要考虑输入的问题。请分三次输出91分，87分，59分所对应的等级结果。<br />**知识点**:条件运算表达式。
```rust
fn main() {
    for _i in 0..3 {
        let mut input = String::new();
        std::io::stdin().read_line(&mut input).expect("Fail to read input");
        let soc = input.trim().parse::<i32>().expect("Fail to parse input");
        match soc {
            90..=100 => println!("A"),
            60..=89 => println!("B"),
            0..=59 => println!("C"),
            _ => println!("Error")
        }
    }
}
```
## 16. 最大公约数
**Rust语言编程题目**：给定两个正整数m=128和n=60，求其最大公约数和最小公倍数。<br />**程序分析**:<br />（1）最小公倍数=输入的两个数之积除于它们的最大公约数，关键是求出最大公约数；<br />（2）求最大公约数用辗转相除法（又名欧几里德算法）<br />1）证明:设c是a和b的最大公约数，记为c=gcd(a,b),a>=b,<br />令r=a mod b<br />设a=kc，b=jc，则k，j互素，否则c不是最大公约数<br />据上，r=a-mb=kc-mjc=(k-mj)c<br />可知r也是c的倍数，且k-mj与j互素，否则与前述k，j互素矛盾,<br />由此可知，b与r的最大公约数也是c，即gcd(a,b)=gcd(b,a mod b)，得证。<br />2）算法描述:<br />第一步:a ÷ b，令r为所得余数（0≤r 第二步:互换:置 a←b，b←r，并返回第一步。<br />**输出格式**:第一行输出最大公约数，第二行输出最小公倍数。<br />**知识点**:循环
```rust
fn main() {
    let m =128;
    let n = 60;
    println!("最大公约数:{}\n最小公倍数:{}",gcd(m,n),lcm(m,n));
}
fn gcd(a:i32,b:i32) -> i32 { if a%b==0 { b } else { gcd(b, a%b)} }
fn lcm(a:i32,b:i32) -> i32 { (a*b)/gcd(a, b )}
// int gcd(int a, int b){ return (b==0) ? a : gcd(b, a%b); }
// gcd(a,b)=gcd(b,a mod b)，即a和b的最大公约数就是a和a%b的最大公约数。
// a*b=gcd(a,b)*lcm(a.b)
```
```rust
// 题解
fn main() {
    let m = 128;
    let n = 60;

    let mut temp_m = m;
    let mut temp_n = n;
    let mut temp_mod = temp_m % temp_n;
    while temp_mod != 0 {
        temp_m = temp_n;
        temp_n = temp_mod;
        temp_mod = temp_m % temp_n;
    }

    println!("{} 和 {} 的最大公约数是 {}", m, n, temp_n);
    println!("{} 和 {} 的最小公倍数是 {}", m, n, m * n / temp_n);
}
```
## 17.统计字符
**Rust语言编程题目:在**控制台随便输入一行字符，分别统计出其中英文字母、空格、数字和其它字符的个数。<br />**程序分析**:可以通过> < 比较判断当前的字符属于什么类型的字符。注入从控制台输入后的最后字符是'\n'。<br />**输出格式**:字母的个数是 x1, 空格的个数是 x2, 数字的个数是x3, 其它字符的个数是 x4。<br />**知识点**:循环，输入
```rust
fn main() {
    let mut input = String::new();
    std::io::stdin().read_line(&mut input).expect("Fail to read input");
    let mut zm = 0;
    let mut kg = 0;
    let mut sz = 0;
    let mut qt = 0;
    for x in input.trim().chars() {
        if (x >= 'a' && x <= 'z')|| (x >= 'A' && x <='Z'){ zm+=1 }
        else if x==' ' { kg+=1 }
        else if x >= '0' && x <= '9' { sz+=1 }
        else {qt+=1 }
    }
    println!("{} {} {} {}",zm,kg,sz,qt)
    // study rust diary 001 -- hello world!
    // 字母的个数是 24, 空格的个数是 6, 数字的个数是3, 其它字符的个数是 3
}
```
## 18.循环计算
**Rust语言编程题目**：求s=a+aa+aaa+aaaa+aa...a的值，其中a是一个数字。例如2+22+222+2222+22222(此时共有5个数相加)，几个数相加由n确定，加的数是几由m确定。求当m = 3， n = 6时的值。<br />**程序分析**:关键是计算出每一项的值。中间的每一项值等于前一项 乘以 10 + m。<br />**输出格式**:a + aa + aaa + ... 的值是 x<br />**知识点**:循环
```rust
fn main(){
    let m =3;
    let n =6;
    let mut num;
    let mut sum = 0;
    let mut vec1 = vec![0];
    for i in 1..=n { // 计算 33 333 333 ，分别存储到 vec
        num = 1;
        for _j in 1..=i {  
            num=num*10
        }
        sum+=(num/10)*m;
        vec1.push(sum);
        // println!("{} {} {}",num,m,sum);
    }
    let mut ans = 0;
    for i in 0..vec1.len() {
        ans += vec1[i];
    }
    println!("{}",ans);
}
```
## 19.完数计算
**Rust语言编程题目**：一个数如果恰好等于它的因子之和，这个数就称为"完数"。例如6=1＋2＋3.编程找出1000以内的所有完数。<br />**程序分析**:对n进行分解质因数，应先找到一个最小的质数k，然后按下述步骤完成:

- 如果这个质数恰等于（小于的时候，继续执行循环）n，则说明分解质因数的过程已经结束，另外 打印出即可。
- 但n能被k整除，则应打印出k的值，并用n除以k的商,作为新的正整数n.重复执行第二步。
- 如果n不能被k整除，则用k+1作为k的值,重复执行第一步。

**输出格式**:每个数占一行。例如:6 = 1 + 2 + 3<br />**知识点**:循环
```rust
fn main() {
    for i in 2..10 {
        if is_prime(i) && is_prime(return_pow(2,i)-1 ) {
            let num = (return_pow(2,i)-1)*return_pow(2,i-1);
            if num < 1000 { println!("{}",num); }
        }
    }
}
fn is_prime(number: i64) -> bool {  // 判断是否是素数
    for i in 2..(number / 2 + 1) {
        if number % i == 0 {
            return false;
        }
    }
    true
}
fn return_pow(x:i64,y:i64) -> i64 {
    let mut ans = 1;
    for _i in 0..y { ans*=x; }
    ans
}
```
```c
#include<stdio.h>
int main()
{
int i, j, s, n; /*变量i控制选定数范围，j控制除数范围，s记录累加因子之和*/
printf("请输入所选范围上限:");
scanf("%d", &n); /* n的值由键盘输入*/
for( i=2; i<=n; i++ )
{
s=0; /*保证每次循环时s的初值为0*/
for( j=1; j<i; j++ )
{
if(i%j == 0) /*判断j是否为i的因子*/
s += j;
}
if(s == i) /*判断因子这和是否和原数相等*/
printf("It's a perfect number:%d\n", i);
}
return 0;
}
```
```rust
fn main() {
    const N: i32 = 1000;

    // 求2 - 1000以内的因数
    for i in 2..=N {
        // i 的 因数和
        let mut sum = 1;
        // 记录并存放因子
        let mut array: Vec<i32> = Vec::new();
        // 每个数的第一个因子一定是1
        array.push(1);

        // 求 i 的质因数
        for j in 2..=i/2 {
            if i % j == 0 {
                // 说明 j 是一个因子
                sum += j;
                array.push(j);
            }
        }

        // 判断 sum 和 i 的值是否相等
        if i == sum {
            // 相等则打印 因子array数组
            print!("{} = ", i);
            let result: Vec<String> = array.iter().map(|x| x.to_string()).collect();
            println!("{}", result.join(" + "));
        }
    }
}
```
## 20. 落球反弹
**Rust语言编程题目**：一球从100米高度自由落下，每次落地后反跳回原高度的一半；再落下，求它在第10次落地时，共经过多少米？第10次反弹多高？<br />扩展:第N次反弹多高呢？<br />**程序分析**:小球第一次落地单独分析，第一次落地时，反弹50米，总共经过100米。小球从第二次开始，经过的高度需要 * 2。反弹高度每次 / 2即可。<br />**输出格式**:小球第 {} 次落地时，反弹 {} 米，总共经过 {} 米<br />**知识点**:循环 浮点数
```rust
fn main() {
    for i in 0..=10 {

        let mut height = 100.0/2.0;
        let mut sum = 100.0 ;
        for _ in 2..=i {
            sum += height*2.0;
            height /= 2.0;
        }
        println!("小球第 {} 次落地时，反弹 {} 米，总共经过 {} 米", i, height, sum);
    }
}
```
## 21.猴子吃桃
**Rust语言编程题目**：猴子吃桃问题:猴子第一天摘下若干个桃子，当即吃了一半，还不瘾，又多吃了一个，第二天早上又将剩下的桃子吃掉一半，又多吃了一个。以后每天早上都吃了前一天剩下，的一半零一个。到第10天早上想再吃时，见只剩下一个桃子了。求第一天共摘了多少。**请使用循环和递归两种方式解决此问题**。<br />**程序分析**:采取逆向思维的方法，从后往前推断。

1. 设x1为前一天桃子数，设x2为第二天桃子数， 则:

x2=x1/2-1, x1=(x2+1)*2<br />x3=x2/2-1, x2=(x3+1)*2<br />以此类推: x前=(x后+1)*2

1. 从第10天可以类推到第1天，是一个循环过程。

**输出格式**:猴子第一天总共摘了 {}个桃子<br />**知识点**:循环 递归
```rust
fn main() {
    let mut sum = 0;
    let mut last = 1;
    for _ in 0..9 {
        last = 2*(last+1);
        sum =  last;
    }
    println!("{}", sum);
}
```
```rust
const DAY:i32 = 10;
const LAST_DAY:i32 = 1;
fn main() {
    println!("{}",deal(1));
}
fn deal(day:i32)->i32 {
    if day == DAY { LAST_DAY } else { (deal(day+1)+1)*2 }
}
```
## 22.多重循环
**Rust语言编程题目**：两个乒乓球队进行比赛，各出三人。甲队为a,b,c三人，乙队为x,y,z三人。已抽签决定比赛名单。有人向队员打听比赛的名单。a说他不和x比，c说他不和x,z比，请编程序找出三队赛手的名单。<br />**程序分析**:指定一个队伍，为这队伍匹配对手。假设指定队伍甲，然后采用循环的方式分别匹配队伍乙中的每位选手。<br />**输出格式**:a -> {}, b -> {}, c -> {}<br />**知识点**:三重循环
```rust
fn main() { 
    let vec = vec!['x','y','z'];
    for a in vec.iter() {
        for b in vec.iter() {
            for c in vec.iter() {
                if a==b || b==c || a==c { continue; }
                if a==&'x' { continue; }
                if c==&'x' { continue; }
                if c==&'z' { continue; }
                println!("a -> {}, b -> {}, c -> {}", a, b, c);
            }
        }
    }
}
```
```rust
fn main() {
    let team = ['x', 'y', 'z'];

    // 为a b c三名选手匹配对手
    for a in team.iter() {
        for b in team.iter() {
            if *a == *b {
                continue;
            }
            for c in team.iter() {
                if *a == *c || *b == *c {
                    continue;
                }
                if *a != 'x' && *c != 'x' && *c != 'z' {
                    println!("a -> {}, b -> {}, c -> {}", a, b, c);
                }
            }
        }
    }
}
```
## 23.打印菱形图案
```rust
   *
  ***
 *****
*******
 *****
  ***
   *

```
```rust
fn main() {
    for i in 0..=2 {
        for _j in 0..(3-i) { print!(" ") }
        for _k in 0..(2*i+1) { print!("*") }
        print!("\n");
    }
    for _ in 0..7 { print!("*")}
    print!("\n");
    for i in 0..4 {
        for _j in 0..(i+1) { print!(" ")}
        for _k in 0..(5-2*i) { print!("*")}
        print!("\n");
    }
}
```
## 24.分数求和
**Rust语言编程题目**：有一分数序列:2/1，3/2，5/3，8/5，13/8，21/13...求:<br />①打印第20个数且计算这个数列的前20项之和。<br />②求这个数列N个数的和（N <= 300）。<br />**程序分析**:请抓住分子与分母的变化规律。当前数的分母等于前一个数的分子 + 分母，分子则等于前一个数的分母，以此类推......<br />**输出格式**:输出分两行打印（如下所示）:<br />第 20 个数是 {} / {}<br />前 20 个数的和为 {}<br />**知识点**:循环
```rust
fn main() {
    let mut 分子 = 2;
    let mut 分母 = 1;
    let mut sum:f64 = 0.0;
    for i in 0..20 {
        println!("{} :{}/{}",i+1,分子,分母);
        sum += (分子 as f64) /(分母 as f64); 
        let 临时变量 = 分母;
        分母 = 分子 ;
        分子 = 临时变量 + 分子; 
    }
    println!("{}",sum);
}
```
## 25. 阶乘求和
**Rust语言编程题目**：求 1 到 N 的每个数的阶乘之后的求和。如:<br />求1+2!+3!+...+20!的和。N <= 30。<br />**程序分析**:之前做过类似的累加题目，这道题只是把累加变成了累乘。把前一个数的阶乘用一个变量保存，当前数的阶乘则就是前一个数的阶乘乘以当前数:f(x) = f(x - 1) * x。最后将结果相加即可。PS:20的阶乘的值是否已经超出了i32类型的范围。<br />**输出格式**:1 到 {} 的每个数的阶乘求和为 {}<br />**知识点**:循环 数据类型
```rust
fn main() {
    let n = 20; // 20!+19!+---+1!
    let mut sum:i64 = 0;
    for i in 1..=n {
        // println!("{} {}", i,jie(i));
        sum += jie(i);
    }
    println!("{}",sum);
}
fn jie(x:i32) -> i64 {
    if x==1 { 1 } else { jie(x-1)*x as i64 }
}
```
## 26.递归练习
**Rust语言编程题目**：递归练习。程序调用自身的编程技巧称为递归（ recursion）。递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法，它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解，递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算，大大地减少了程序的代码量。<br />（1）请使用递归的方法求8!。<br />（2）请使用递归的方法求N!，N>=1且N<=10。<br />**程序分析**:首先找出递归公式，然后依次求值。<br />**输出格式**:{} 的阶乘等于 {}<br />**知识点**:递归、函数
```rust
fn main() {
    let n = 8; 
    println!("{} {}", n,jie(n));
}
fn jie(x:i32) -> i64 {
    if x==1||x==0 { 1 } else if x>=2 { jie(x-1)*x as i64 } else { -1 }
}
```
## 27.递归逆序
**Rust语言编程题目**：递归练习。程序调用自身的编程技巧称为递归（ recursion）。递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法，它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解，递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算，大大地减少了程序的代码量。<br />利用递归函数调用方式，将所输入的5个字符，以相反顺序打印出来。<br />**程序分析**:无<br />**输出格式**:逆序输出即可<br />**知识点**:递归
```rust
fn main() {
    let mut input = String::new();
    std::io::stdin().read_line(&mut input).expect("Fail to read input");
    let mut vec: Vec<char>= Vec::new();
    for x in input.chars() {
        vec.push(x)
    }
    vec.pop();vec.pop();
    deal(&mut vec);
}
fn deal(str: &mut Vec<char>) {
    if str.len()==1 { return print!("{}", str[0]); }
    else { print!("{}", str[str.len() - 1]);str.pop();deal(str) }
}
```
```rust
fn main() {
   plain(5);
}

fn plain(n: i32) {
    if n <= 1 {
        let mut text = String::new();
        std::io::stdin().read_line(&mut text).expect("read line error!");
        print!("{} ", text.trim());
    } else {
        let mut text = String::new();
        std::io::stdin().read_line(&mut text).expect("read line error!");
        plain(n - 1);
        print!("{} ", text.trim());
    }
}
```
## 28.递归回推
**Rust语言编程题目**：递归练习。程序调用自身的编程技巧称为递归（ recursion）。递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法，它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解，递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算，大大地减少了程序的代码量。<br />有5个人坐在一起，问第五个人多少岁？他说比第4个人大2岁。问第4个人岁数，他说比第3个人大2岁。问第三个人，又说比第2人大两岁。问第2个人，说比第一个人大两岁。最后问第一个人，他说是10岁。请问第五个人多大？<br />**程序分析**:利用递归的方法，递归分为回推和递推两个阶段。要想知道第五个人岁数，需知道第四人的岁数，依次类推，推到第一人（10岁），再往回推。<br />**输出格式**:直接输出年龄即可。<br />**知识点**:递归
```rust
fn main() {
    let result = age(5);
     println!("{}", result);
 }
 fn age(n: i32) -> i32 {
    if n == 1 { 10 }
    else { age(n - 1) + 2 }
 }
```
## 29.整数分解
**Rust语言编程题目**：咱们从呱呱坠地开始，就开始接触数字。生活中无时无刻的也都充满着数组。假设给你一个数字，是否可以将其中的每位数分解呢？<br />输入一个不多于5位的**正整数**。然后满足以下两个要求:<br />1、求它是几位数<br />2、逆序打印出各位数字。<br />**程序分析**:学会分解出每一位数。如何得到一个数的每位数呢？具体分解过程详见代码注释。<br />**输出格式**:{}为 {} 位数,逆序为:xxx<br />**知识点**:匹配
```rust
fn main() {
    let mut input = String::new();
    std::io::stdin().read_line(&mut input).expect("Fail to read input");
    let mut vec: Vec<char>= Vec::new();
    for x in input.trim().chars() {
        vec.push(x)
    }
    print!("{}为 {} 位数 ,逆序为:",input.trim(),vec.len());
    deal(&mut vec);
}
fn deal(str: &mut Vec<char>) {
    if str.len()==1 { return print!("{}", str[0]); }
    else { print!("{}", str[str.len() - 1]);str.pop();deal(str) }
}
```
## 30. 回文数
**Rust语言编程题目**：“回文”是指正读反读都能读通的句子，它是古今中外都有的一种修辞方式和文字游戏，如“我为人人，人人为我”等。在数学中也有这样一类数字有这样的特征，成为回文数（palindrome number）。一个5位数，判断它是不是回文数。即12321是回文数，个位与万位相同，十位与千位相同。<br />**程序分析**:学会分解出每一位数。如何得到一个数的每位数呢？具体分解过程详见代码注释。<br />**输出格式**:如果是回文数:{} 是一个回文数<br />如果不是回文数:{} 不是一个回文数<br />**知识点**:匹配
```rust
fn main() {
    let mut input = String::new();
    std::io::stdin().read_line(&mut input).expect("Fail to read input");
    let mut vec: Vec<char>= Vec::new();
    for x in input.trim().chars() { vec.push(x) }
    if input.trim().len()!=5 { println!("请输入一个5位数");return; }
    let mut flag = true;
    for i in 0..3 {
        if vec[i]!=vec[4-i] { flag = false; }
    }
    if flag { println!("{} 是一个回文数",input.trim()); }
    else { println!("{} 不是一个回文数",input.trim()); }
}
```
## 31.判断星期几
**Rust语言编程题目**：请输入星期几的第一个字母来判断一下是星期几，如果第一个字母一样，则继续判断第二个字母。<br />**程序分析**:用match匹配语句比较好，如果第一个字母一样，则判断用match匹配或if语句判断第二个字母。推荐使用match匹配语句。<br />**输出格式**:请输入首字母:<br />s<br />请输入下一个字母:<br />u<br />Sunday!<br />**知识点**:匹配
```rust
fn main() {
    let mut input  = String::new();
    std::io::stdin().read_line(&mut input).expect("Fail to read input");
    match input.trim().parse::<char>().unwrap() {
        'm' => println!("Monday"),
        'w' => println!("Wednesday"),
        'f' => println!("Friday"),
        't' => {
            println!("Unable to judge,input the next word");
            let mut input  = String::new();
            std::io::stdin().read_line(&mut input).expect("Fail to read input");
            match input.trim().parse::<char>().unwrap() {
                'u' => println!("Tuesday"),
                'h' => println!("Thursday"),
                _ => println!("Erro")
            }
        }
        's' => {
            println!("Unable to judge,input the next word");
            let mut input  = String::new();
            std::io::stdin().read_line(&mut input).expect("Fail to read input");
            match input.trim().parse::<char>().unwrap() {
                'a' => println!("Saturday"),
                'u' => println!("Sunday"),
                _ => println!("Erro")
            }
        }
        _ => println!("Erro")
    }
}
```
## 32.迭代器
**Rust语言编程题目**：字符串在编程语言中是最常见的类型之一。现在有一个要求，让你删除一个字符串中的指定字母，如:字符串 "aca"，删除其中的 a 字母。<br />**程序分析**:可以考虑使用迭代器进行操作。<br />**输入字符串**:acafafsda<br />**输出格式**:直接输出删除指定字母后的字符串。<br />示例:string = {}<br />**知识点**:迭代器 闭包
```rust
fn main() {
    let del_chars ='a';
    let str = "acafafsda";

    let s: String = str.chars().into_iter().filter(|x| *x != del_chars).collect();
    let ans:String = str.chars().into_iter().filter(|x| x != &del_chars).collect();
    println!("{}", ans);
    println!("{}",s);
}
```
相关资料:
## 33.质数判断
**Rust语言编程题目**：质数是指在大于1的自然数中，除了1和它本身以外不再有其他因数的自然数。请写出程序，判断一个数字是否为质数。<br />**程序分析**:质数（prime number）又称素数，有无限个。一个大于1的自然数，除了1和它本身外，不能被其他自然数整除。<br />**判断数字**:3571<br />**输出格式**:3571 是/不是一个质数<br />**知识点**:循环
```rust
fn main() {
    let num = 3571 ;
    print!("{} ", num);
    if is_prime(num) { print!("是一个质数")}
    else { print!("不是一个质数")}
}
fn is_prime(number: i64) -> bool {  // 判断是否是素数
    for i in 2..(number / 2 + 1) {
        if number % i == 0 {
            return false;
        }
    }
    true
}
```
## 34.函数练习
**Rust语言编程题目**：函数是指一段可以直接被另一段程序或代码引用的程序或代码。也叫做子程序、（OOP中）方法。一个较大的程序一般应分为若干个程序块，每一个模块用来实现一个特定的功能。所有的高级语言中都有子程序这个概念，用子程序实现模块的功能。<br />本题是练习函数的使用，编写一个求两个数的和的函数。如:a = 5, b = 6。<br />**程序分析**:无<br />**输出格式**:a + b = {}<br />**知识点**:函数
```rust
fn main() {
    let a=1; let b =2 ;
    println!("a + b = {}",add(a, b));
}
fn add(x: i32, y: i32) -> i32 { x + y }
```
## 35.字符串反转
**Rust语言编程题目**：字符串反转练习，如将字符串 "i like rust!" 反转为"!tsur ekil i"。不允许使用rev方法。请自定义一个字符串反转函数，该函数不允许有返回值。但是经过该函数后，字符串会反转。<br />**程序分析**:定义一个没有返回值函数来反转字符串，那肯定要求参数是可变引用传值。<br />**输出格式**:!tsur ekil i<br />**知识点**:函数、所有权、借用、引用、字符串
```rust
fn main() {
    let mut input = String::new();
    std::io::stdin().read_line(&mut input).expect("Fail to read input");
    rev(input.trim());
}
fn rev(string: &str){
    let mut ans:Vec<char> = Vec::new();
    for i in string.chars() { ans.push(i); }
    let len = ans.len();
    for i in 0..len { 
        print!("{}", ans[len - i - 1]);
    }
    //println!("{:?}", ans);
}
```
```rust
fn main() {
    let mut s = String::from("i like rust!");
    reverse(&mut s);
    println!("{}", s);
}

fn reverse(s: &mut String) {
    let length = s.chars().count();
    for i in 0..length / 2 {
        let end_index = length - 1 - i;
        let cc = s.chars().nth(i).unwrap();
        let ec = s.chars().nth(end_index).unwrap();
        s.replace_range(i..i + 1, ec.to_string().as_str());
        s.replace_range(end_index..end_index + 1, cc.to_string().as_str());
    }
}
```
## 36.查找素数
**Rust语言编程题目**：求100之内的素数。<br />**程序分析**:质数（prime number）又称素数，有无限个。一个大于1的自然数，除了1和它本身外，不能被其他自然数整除。<br />**输出格式**:!tsur ekil i<br />**知识点**:函数、所有权、借用、引用、字符串
```rust
fn main() {
    let mut k = 0;
    for i in 2..=100 {
        if is_prime(i) { print!("{}\t", i);k+=1; }
        if k==5 { print!("\n");k=0 }
    }
}
fn is_prime(number: i64) -> bool {  // 判断是否是素数
    for i in 2..(number / 2 + 1) {
        if number % i == 0 {
            return false;
        }
    }
    true
}
```
## 37.选择法排序
**Rust语言编程题目**：排序是计算机内经常进行的一种操作，其目的是将一组“无序”的记录序列调整为“有序”的记录序列。这道题就来考察下排序，对下面的10个数进行排序。<br />[1, 4, 3, 6, 8, 2, 9, 0, 7, 5] <br />**程序分析**:可以利用选择法，即从后9个比较过程中，选择一个最小的与第一个元素交换， 下次类推，即用第二个元素与后8个进行比较，并进行交换。也可以利用插入排序法等等。<br />**输出格式**:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]<br />**知识点**:数据结构简单排序（选择排序，插入排序）
```rust
fn main() {
    // 冒泡排序
    let mut vec = [1, 4, 3, 6, 8, 2, 9, 0, 7, 5];
    for i in 0..vec.len() {
        for j in 0..i {
            // println!("{} {}", vec[i], vec[j]);
            if vec[j] > vec[i] {
                let tem = vec[j];
                vec[j] = vec[i];
                vec[i] = tem;
            }
        }
    }
    println!("{:?}", vec);
}
```
```rust
fn main() {
    let mut vec = vec![1, 4, 3, 6, 8, 2, 9, 0, 7, 5];
    // test37_insert_sort(&mut vec);
    test37_select_sort(&mut vec);
    println!("{:?}", vec);
}

/// 插入排序
fn test37_insert_sort(vec: &mut Vec<i32>) {
    for i in 0..vec.len() {
        let mut j = i;
        while j > 0 {
            if vec[j] < vec[j - 1] {
                // 交换值
                let temp = vec[j];
                vec[j] = vec[j - 1];
                vec[j - 1] = temp;
            }
            j -= 1;
        }
    }
}

/// 选择排序
fn test37_select_sort(vec: &mut Vec<i32>) {
    for i in 0..vec.len() - 1 {
        let mut mix_index = i;
        for j in i + 1..vec.len() {
            if vec[mix_index] > vec[j] {
                mix_index = j;
            }
        }

        // 如果找到了比当前小的值
        // 交换
        if mix_index != i {
            let temp = vec[i];
            vec[i] = vec[mix_index];
            vec[mix_index] = temp;
        }
    }
}
```
## 38.矩阵行列式
**Rust语言编程题目**：行列式在数学中，是一个函数，其定义域为det的矩阵A，取值为一个标量，写作det(A)或 | A | 。无论是在线性代数、多项式理论，还是在微积分学中（比如说换元积分法中），行列式作为基本的数学工具，都有着重要的应用。<br />求下面行列式的值:<br />1 2 3 <br />8 0 4 <br />7 6 5 <br />**程序分析**:三阶行列式的值为a11a22a33+a12a23a31+a13a21a32-a11a23a32-a12a21a33-a13a22a31。使用二维数组即可。<br />**输出格式**:直接输出结果<br />**知识点**:二维数组
```rust
fn main() {
    let a = [[1, 2, 3], [8, 0, 4], [7, 6, 5]];
    let mut sum = 0;
    // a11a22a33+a12a23a31+a13a21a32-a11a23a32-a12a21a33-a13a22a31
    sum = a[0][0] * a[1][1] * a[2][2] + a[0][1] * a[1][2] * a[2][0] + a[0][2] * a[1][0] * a[2][1]
        - a[0][0] * a[1][2] * a[2][1] - a[0][1] * a[1][0] * a[2][2] - a[0][2] * a[1][1] * a[2][0];

    println!("行列式的值为 {}", sum);
}
```
## 39.插入数组
**Rust语言编程题目**：有一个已经排好序的数组。现输入一个数，要求按原来的规律将它插入数组中。<br />序列如下:<br />[1, 3, 6, 10, 23, 36, 45, 52, 67, 89, 99] <br />**程序分析**:首先判断此数是否大于最后一个数,然后再考虑插入中间的数的情况,插入后此元素之后的数,依次后移一个位置。这个过程类似于插入排序。<br />**输出格式**:直接输出结果<br />**知识点**:排序
```rust
fn main() {
    let mut vec = vec![1, 3, 6, 10, 23, 36, 45, 52, 67, 89, 99];
    let mut input = String::new();
    std::io::stdin().read_line(&mut input).expect("Fail to read line");
    let num = input.trim().parse::<i32>().unwrap();
    // println!("{}", num);
    for i in 0..vec.len()-1 {
        if (num<vec[i]&&num>vec[i+1])||(num>vec[i]&&num<vec[i+1]) {
            let mut tem = vec![num];
            let last = vec[vec.len()-1];
            println!("发现 {} {}", vec[i], vec[i+1]);
            println!("发现的下标{}",i);
            for j in i+1..vec.len() {
                println!("挪动下标{}",j);
                tem.push(vec[j]);
            }
            println!("{:?}",tem);
            let mut k =0;
            for j in i+1..vec.len() {
                vec[j]=tem[k];k+=1;
            }
            vec.push(last);
        }
    }
    println!("{:?}",vec);
}
```
```rust
fn main() {
    let mut vec = vec![1, 3, 6, 10, 23, 36, 45, 52, 67, 89, 99];

    let mut input_data = String::new();
    std::io::stdin().read_line(&mut input_data).expect("read line error!");

    match input_data.trim().parse::<i32>() {
        Ok(data) => {
            vec.push(data);
            let mut index = vec.len() - 1;
            while index > 0 {
                // 如果前面的元素大，就交互
                // 类似于插入排序
                if vec[index - 1] > vec[index] {
                    let mut temp = vec[index - 1];
                    vec[index - 1] = vec[index];
                    vec[index] = temp;
                } else {
                    // 如果不需要交互，直接退出循环
                    break;
                }
                index -= 1;
            }

            println!("{:?}", vec);
        }
        Err(_) => {
            println!("输入错误!");
        }
    }
}
```
## 40.数组逆序输出
**Rust语言编程题目**：前面做过字符串的逆序输出，现给定一个数组，将这个数组逆序输出。<br />给定的数组如下:<br />[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] <br />**程序分析**:循环数组长度的一半，用第一个元素与最后一个元素交换，第二个与倒数第二个元素交换，以此类推，直到所有元素交换完毕。<br />**输出格式**:直接输出结果<br />**知识点**:循环、数组
```rust
fn main() {
    let arr  = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
    let mut vec:Vec<i32> = Vec::new();
    let k = arr.len();
    for i in 0..arr.len() {
        vec.push(arr[k-i-1]);
        // println!("{}", arr[k-i-1]);
    }
    println!("{:?}", vec);
}
```
```rust
fn main() {
    let mut array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

    for i in 0..array.len() / 2 {
        let mut temp = array[i];
        array[i] = array[array.len() - 1 - i];
        array[array.len() - 1 - i] = temp;
    }

    println!("{:?}", array);
}
```
## 41.static定义
**Rust语言编程题目**：static关键字比较特殊。学习static定义静态变量的用法。<br />要求:编写一个函数，在函数中声明一个static修饰的i32类型数字。每次让其增加1。然后在main函数中，连续调用三次，观察static修饰的变量值的变化。<br />注意:使用可变的static修饰变量需要将其抱在unsafe代码块中。<br />**程序分析**:static修饰的变量只被初始化一次，并且保持最近的值，哪怕创建它的函数已经结束，这个变量也不会被释放。<br />**输出格式**:直接输出结果<br />**知识点**:static
```rust
fn main() {
    unsafe {
        static_test();
        static_test();
        static_test();
        static_test();
        static_test();
    }
}
unsafe fn static_test() {
    static mut COUNT:i32 = 0;
    COUNT += 1;
    println!("COUNT = {}", COUNT);
}
```
## 42.冒泡排序
**Rust语言编程题目**：在第39题已经练习过插入排序和选择排序。今天来练习下另一种排序——冒泡排序。<br />冒泡排序（Bubble Sort），是一种计算机科学领域的较简单的排序算法。<br />它重复地走访过要排序的元素列，依次比较两个相邻的元素，如果顺序（如从大到小、首字母从Z到A）错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换，也就是说该元素列已经排序完成。<br />这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端（升序或降序排列），就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样，故名“冒泡排序”。<br />要求:请将下面的数组使用冒泡排序算法排序。
```rust
fn main() {
    // 冒泡排序
    let mut vec = [5, 3, 7, 9, 1, 4, 2, 0, 6, 8];
    for i in 0..vec.len() {
        for j in 0..i {
            // println!("{} {}", vec[i], vec[j]);
            if vec[j] > vec[i] {
                let tem = vec[j];
                vec[j] = vec[i];
                vec[i] = tem;
            }
        }
    }
    println!("{:?}", vec);
}
```
## 43.static修饰
**Rust语言编程题目**：在第41题已经练习过static修饰变量的用法。今天再来练习下static修饰变量的另一种用法。<br />要求:外部定义一个num变量，然后在代码块中定义另一个num变量且使用static修饰。是这两个变量循环三次，每次增加1，观察两个变量的值。<br />**程序分析**:static修饰的变量只被初始化一次，并且保持最近的值，哪怕创建它的函数已经结束，这个变量也不会被释放。<br />**输出格式**:直接输出结果<br />**知识点**:static
```rust
fn main() {
    let mut num  = 2;
    for _i in 0..3 {
        println!("num 变量为 {}", num);
        num += 1;
        unsafe {
            static mut num:i32 = 1;
            println!("内置代码块(static) num变量为{}", num);
            num += 1;
        }
    }
}
```
## 44.static练习
**Rust语言编程题目**：在第41题和43题已经练习过static修饰变量的用法。今天再来练习下static修饰变量的另一种用法。理解Rust中被static修饰的变量不能重新使用其变量名。<br />要求:外部定义一个static修饰的变量，在函数内部，定义重名变量，运行代码，观察结果。<br />**程序分析**:static先修饰的变量不能重新使用其变量名。<br />**输出格式**:程序会报错<br />**知识点**:static
```rust
static test = 3;
fn main() {
    let test = 5;
}
/* 
 --> src\main.rs:3:9
  |
1 | static test = 3;
  | ---------------- the static `test` is defined here
2 | fn main() {
3 |     let test = 5;
  |         ^^^^ cannot be named the same as a static 

error: missing type for `static` item
 --> src\main.rs:1:8
  |
1 | static test = 3;
  |        ^^^^ help: provide a type for the static variable: `test: i32`
*/
```
## 45.希尔排序
**Rust语言编程题目**：在第39题和42题已经练习过选择排序，插入排序，冒泡排序。今天再来练习新的排序算法——希尔排序。希尔排序(Shell Sort)是插入排序的一种，它是针对直接插入排序算法的改进。希尔排序又称缩小增量排序，因 DL.Shell 于 1959 年提出而得名。它通过比较相距一定间隔的元素来进行，各趟比较所用的距离随着算法的进行而减小，直到只比较相邻元素的最后一趟排序为止。<br />要求:请将下面的数组使用冒泡排序算法排序。<br />[5, 3, 7, 9, 1, 4, 2, 0, 6, 8] <br />**程序分析**:先写出插入排序，插入排序的间隔是1，而希尔排序每次的间隔则不一样。<br />**输出格式**:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]<br />**知识点**:插入排序 希尔排序<br />

```rust

fn main() {
    // 希尔排序
    let mut arr = [5, 3, 7, 9, 1, 4, 2, 0, 6, 8];
    let mut gap = arr.len()/2;
    loop {
    println!("gap={}", gap);
    for i in 0..arr.len()/2 {
        let mut k =i;
        let mut sum = 0; 
        loop {
            if k>=arr.len() { break; }
            print!("{} ",arr[k]);
            k+=gap;
            sum+=1;
        }
        print!("\n");
        for a in (i..=i+(sum-1)*gap).filter(|x| (x-i)%gap==0 ) {
            for b in (a..=i+(sum-1)*gap).filter(|x| (x-a)%gap==0 ) {
                if arr[a]>arr[b] { 
                    let tem = arr[a];
                    arr[a] = arr[b];
                    arr[b] = tem;
                }
            }
        }
    }
    gap-=1;
    if gap==0 { break }
}
    for i in arr { print!("{} ",i)}
    println!("");
    println!("{:?}",arr);
}
```
```rust
fn main() {
   let mut a = [5, 3, 7, 9, 1, 4, 2, 0, 6, 8];

    let mut gap = a.len() / 2;
    while gap > 0 {
        // 插入排序
        for i in gap..a.len() {
            let mut j = i;
            while j > 0 && j >= gap {
                // 交换
                if a[j - gap] > a[j] {
                    a[j - gap] = a[j - gap] ^ a[j];
                    a[j] = a[j - gap] ^ a[j];
                    a[j - gap] = a[j - gap] ^ a[j];
                }
                j -= gap;
            }
        }
        gap /= 2;
    }

    println!("{:?}", a);
}
```
## 46.匹配练习
**Rust语言编程题目**：在编写程序的时候，常常因为疏忽或者懒惰没有处理函数调用的返回值，给代码的稳定性增添了隐患。如果是Rust编程，你不用有这样的顾虑。学习Rust中Result的用法。要求:编写一个程序，将字符串转化为i32类型。如果字符串不合法，则提示错误信息。如果字符串合法，则正常输出转化后的数字。<br />**程序分析**:可以考虑使用match与Result，按照匹配结果分别输出。<br />**输出格式**:按照要求输出即可。<br />**知识点**:match Result
```rust
fn main() {
    let mut input = String::new();
    std::io::stdin().read_line(&mut input).expect("Fail to read input");
    match input.trim().parse::<i32>() {
        Ok(data) => println!("str 转 i32 -> {}", data),
        Err(err) => println!("str 转 i32 错误原因 {}", err),
    }
}
```
## 47.unwrap
**Rust语言编程题目**：编写程序练习unwrap和expect方法。<br />_**unwrap()**_ 函数可以看出 Result 中类型，可能是 _**Ok**_，也可能是 _**Err**_。如果 Result 中包裹的类型是 _**Ok**_，那么 _**unwrap()**_ 则返回它的值。如果 Result 中的类型是 _**Err**_，_**unwrap()**_ 则会让程序崩溃。<br />_**expect()**_ 的工作方式类似于 _**unwrap()**_，假如 Result 是 _**Err**_，_**expect()**_ 将会使程序崩溃**并且**将其中的字符串内容 —— “Parse failed.”展示在标准输出中。<br />**程序分析**:可以考虑使用match与Result，按照匹配结果分别输出。<br />**输出格式**:无。<br />**知识点**:unwrap expect
```rust
fn main() {
    let str = "23";

    let expect_num = str.parse::<i32>().expect("fail to parse!");
    let unwrap_num = str.parse::<i32>().unwrap();

    dbg!(expect_num);
    dbg!(unwrap_num);
}
```
结果:
```rust
[src\main.rs:7] expect_num = 23
[src\main.rs:8] unwrap_num = 23
```
## 48.宏macro
**Rust语言编程题目**：Rust 对宏（macro）有着非常好的支持。宏能够使得你能够通过写代码的方式来生成代码，这通常被称为元编程（metaprogramming）。<br />宏提供了类似函数的功能，但是没有运行时开销。但是，因为宏会在编译期进行展开（expand），所以它会有一些编译期的开销。<br />要求:编写一个宏，可以求两个数的和。<br />**程序分析**:暂时不需要考虑类型。<br />**输出格式**:无。<br />**知识点**:marco rules
```rust
macro_rules! test_macro {
    ($a: expr, $b: expr) => {
        $a + $b
    };
}
fn main() {
    let a = test_macro!(1.1, 2 as f64);
    dbg!(a);
}
```
## 49.Option用法
**Rust语言编程题目**：在Rust中不像Java那样，存在null值。Option<T>是定义在标准库的一个枚举，用来防止意外的使用null。Option<T>是一个枚举，它有两个变量:

- None，表明失败或缺少值
- Some(value)，元组结构体，封装了一个 T 类型的值 value

要求:编写一个程序练习Option的用法。<br />**程序分析**:无。<br />**输出格式**:无。<br />**知识点**:Option<T>
```rust
fn main() {
    let arr = [1,2];
    dbg!(arr);
    dbg!(arr.get(0));
    dbg!(arr.get(2));
    // 对于返回的Option<T>，可以使用match匹配
}
```
