learning-rust/part2/src/main.rs

289 lines
10 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// ============================================================
// Rust 基础巩固练习 (变量类型 + 流程控制)
// 在做完所有题目之前,建议先注释掉 main 函数中的代码,
// 每题单独写一个函数来测试,然后在 main 中调用。
// ============================================================
fn main() {
println!("Hello, world!");
// ex1_variables();
// ex2_scalar_types();
// ex3_compound_types();
// ex4_functions();
// ex5_control_flow();
// ex6_loops();
mini_guessing_game();
// ex8_stats();
}
// ============================================================
// 练习1变量与可变性
// ============================================================
// 1. 声明一个不可变变量 x = 10尝试修改它为 20看编译器报什么错
// 然后把报错的那行注释掉。
// 2. 声明一个可变变量 y = 5然后将它修改为 15打印修改前后的值。
// 3. 使用 let 遮蔽shadowing声明变量 z = "hello"
// 然后用 let 再次声明 z将其值改为 z.len()(即字符串长度),
// 再用 let 声明 z将其值改为 z * 2。打印每次遮蔽后的值。
#[allow(dead_code)]
fn ex1_variables() {
// TODO: 在这里写你的代码
let x = 10;
// error: could not compile `part2` (bin "part2") due to 1 previous error; 10 warnings emitted
// x = 20;
let mut y = 5;
println!("修改前:{}", y);
y = 15;
println!("修改后:{}", y);
let z = "hello";
println!("z:{}", z);
let z = z.len();
println!("z:{}", z);
let z = z * 2;
println!("z:{}", z);
}
// ============================================================
// 练习2基本数据类型
// ============================================================
// 1. 声明 u8, i32, f64, bool, char 类型的变量各一个,赋予合理的值。
// 2. 使用 as 关键字将 u8 转换为 i32将 f64 转换为 i32观察小数部分被截断
// 3. 打印字符 char 的数值表示(用 as u32
// 4. 声明一个 usize 变量 = 5让它减去 10观察 underflow 的编译报错或用 wrapping_sub
#[allow(dead_code)]
fn ex2_scalar_types() {
// TODO: 在这里写你的代码
let u8_var: u8 = 42;
let i32_var: i32 = 128;
let f64_var: f64 = 3.14;
let bool_var: bool = true;
let char_var = '2';
println!("u8 as i32: {}", u8_var as i32);
println!("f64 as i32: {}", f64_var as i32);
println!("char as u32: {}", char_var as u32);
let usize_var: usize = 5;
// error: usize_var - 10: attempt to compute `5_usize - 10_usize`, which would overflow
// usize_var.wrapping_sub(10): 18446744073709551611
println!("usize_var - 10: {}", usize_var.wrapping_sub(10));
}
// ============================================================
// 练习3复合类型 —— 元组 (Tuple) 和数组 (Array)
// ============================================================
// 1. 声明一个元组 tup: (i32, f64, &str) = (42, 3.14, "rust")
// 分别用解构和 .索引 两种方式取出并打印三个元素。
// 2. 声明一个数组 arr: [i32; 5] = [1, 2, 3, 4, 5]
// 用 for 循环遍历打印每个元素,打印数组长度。
// 3. 尝试访问 arr[10],观察编译报错 vs 运行时 panic 的区别——
// 先用常量索引(编译期检查),再用变量索引(运行期检查)。
#[allow(dead_code)]
fn ex3_compound_types() {
// TODO: 在这里写你的代码
let tup: (i32, f64, &str) = (42, 3.14, "rust");
let (a, b, c) = tup;
println!("tup: {}, {}, {}", a, b, c);
let a1 = tup.0;
let b1 = tup.1;
let c1 = tup.2;
println!("tup: {}, {}, {}", a1, b1, c1);
let arr: [i32; 5] = [1, 2, 3, 4, 5];
for i in 0..arr.len() {
println!("arr[{}]: {}", i, arr[i]);
}
println!("arr length: {}", arr.len());
// arr[10]; error: index out of bounds: the len is 5 but the index is 10
}
// ============================================================
// 练习4函数定义与调用
// ============================================================
// 1. 写一个函数 add(a: i32, b: i32) -> i32返回两数之和在 main 中调它。
// 2. 写一个函数 factorial(n: u32) -> u32用循环计算 n 的阶乘。
// 提示n! = 1 × 2 × 3 × ... × n0! = 1
// 3. 写一个函数 is_even(n: i32) -> bool判断一个数是否为偶数。
// 4. 写一个无返回值的函数 greet(name: &str),打印 "你好,{name}"。
#[allow(dead_code)]
fn add(a: i32, b: i32) -> i32 {
a + b
}
#[allow(dead_code)]
fn factorial(n: u32) -> u32 {
let mut result = 1;
for i in 1..=n {
result *= i;
}
result
}
#[allow(dead_code)]
fn is_even(n: i32) -> bool {
n % 2 == 0
}
#[allow(dead_code)]
fn greet(name: &str) {
// TODO
println!("你好,{}", name)
}
fn ex4_functions() {
// 在这里调用上面四个函数进行测试
println!("add(1, 2): {}", add(1, 2));
println!("factorial(5): {}", factorial(5));
println!("is_even(5): {}", is_even(5));
greet("Rust");
}
// ============================================================
// 练习5控制流 —— if / else if / else
// ============================================================
// 1. 写一个函数 grade(score: u32) -> &'static str根据分数返回等级
// 90-100 → "A", 80-89 → "B", 70-79 → "C", 60-69 → "D", 0-59 → "F"
// 2. 写一个函数 fizzbuzz(n: u32),打印 1 到 n
// 能被 3 整除打印 "Fizz",能被 5 整除打印 "Buzz"
// 能同时被 3 和 5 整除打印 "FizzBuzz",否则打印数字本身。
// 3. 使用 if 作为表达式let x = if ... { ... } else { ... };
// 根据一个 bool 变量给另一个变量赋不同的值。
#[allow(dead_code)]
fn grade(score: u32) -> &'static str {
let mut x = "";
if score >= 90 && score <= 100 {
x = "A";
} else if score >= 80 && score < 90 {
x = "B";
} else if score >= 70 && score < 80 {
x = "C";
} else if score >= 60 && score < 70 {
x = "D";
} else {
x = "F";
};
return x;
}
#[allow(dead_code)]
fn fizzbuzz(n: u32) {
for i in (1..=n) {
if i % 3 == 0 && i % 5 == 0 {
println!("FizzBuzz")
} else if i % 3 == 0 {
println!("Fizz")
} else if i % 5 == 0 {
println!("Buzz")
} else {
println!("{}", i)
}
}
}
fn ex5_control_flow() {
// 在这里测试
let score = 89;
let condition = true;
let n = if condition { 100 } else { 50 };
println!("grade{}", grade(score));
fizzbuzz(n);
}
// ============================================================
// 练习6循环 —— loop / while / for
// ============================================================
// 1. 用 loop 写一个无限循环,内部用计数器从 1 开始累加,
// 当计数达到 100 时用 break 退出,并用 break 返回值打印最终结果。
// 2. 用 while 循环打印 10 到 1 的倒数。
// 3. 用 for 循环遍历一个数组 [10, 20, 30, 40, 50],打印每个元素及其索引。
// 提示:用 .iter().enumerate()
// 4. 用 for 循环配合 Range打印 1..=5 的每个数的平方。
#[allow(dead_code)]
fn ex6_loops() {
// TODO: 在这里写你的代码
let mut sum = 0;
let mut i = 1;
let result = loop {
sum += i;
if i == 100 {
break sum;
};
i += 1;
};
println!("sum: {}", result);
let mut i = 10;
while i > 0 {
println!("倒数: {}", i);
i -= 1;
}
let arr = [10, 20, 30, 40, 50];
for (i, item) in arr.iter().enumerate() {
println!("index: {}, value: {}", i, item);
}
for i in 1..=5 {
println!("{} 的平方是 {}", i, i * i);
}
}
// ============================================================
// 练习7综合猜数字游戏简化版
// ============================================================
// 写一个函数 mini_guessing_game(),模拟一个简化的猜数字游戏:
// - 设定一个固定的秘密数字(比如 42
// - 用一个数组 [10, 50, 35, 60, 42] 模拟玩家的猜数字序列
// - 遍历数组,对每次猜测判断:
// - 猜小了 → 打印 "{} 太小了!"
// - 猜大了 → 打印 "{} 太大了!"
// - 猜对了 → 打印 "{} 猜对了!" 并退出循环
// 提示for + if/else + break
#[allow(dead_code)]
fn mini_guessing_game() {
// TODO: 在这里写你的代码
let secret_number = 62;
let guesses: [i32; 5] = [10, 50, 35, 60, 42];
for (i, guess) in guesses.iter().enumerate() {
if guess < &secret_number {
println!("{}次猜测,{} 太小了!", i + 1, guess);
} else if guess > &secret_number {
println!("{}次猜测,{} 太大了!", i + 1, guess);
} else {
println!("{}次猜测,{} 猜对了!", i + 1, guess);
break;
};
}
}
// ============================================================
// 练习8综合统计字符串中的字母
// ============================================================
// 写一个函数 count_letters(s: &str) -> (u32, u32),接收一个字符串切片,
// 统计其中大写字母和小写字母的数量,以元组形式返回。
// - 提示1用 .chars() 获取字符迭代器
// - 提示2用 char::is_uppercase() 和 char::is_lowercase() 判断
// - 提示3在 ex8_stats 中调用这个函数,用两个不同的字符串测试
#[allow(dead_code)]
fn count_letters(s: &str) -> (u32, u32) {
// TODO
let chars = s.chars();
let tup: (u32, u32) = (0, 0);
let (mut upper, mut lower) = tup;
for c in chars {
if c.is_uppercase() {
upper += 1;
} else if c.is_lowercase() {
lower += 1;
}
}
(upper, lower)
}
fn ex8_stats() {
// 在这里测试 count_letters
let (upper, lower) = count_letters("Hello, World!");
println!("大写字母数量:{},小写字母数量:{}", upper, lower);
}