41.使用模块的函数
mod 是用于创建模块的关键字。模块是一种组织代码的方式,它可以包含函数 (fn)、结构体 (struct)、枚举 (enum)、常量 (const)、其他模块 (mod) 等。模块的函数一般是私有的,需要使用pub关键词将其暴露
- // modules1.rs
- // Execute `rustlings hint modules1` or use the `hint` watch subcommand for a hint.
-
- // I AM NOT DONE
-
- mod sausage_factory {
- // Don't let anybody outside of this module see this!
- fn get_secret_recipe() -> String {
- String::from("Ginger")
- }
-
- pub fn make_sausage() {
- get_secret_recipe();
- println!("sausage!");
- }
- }
-
- fn main() {
- sausage_factory::make_sausage();
- }
42.暴露读取私有方法的函数的属性的模板变量,以选择性地公布部分属性(设置为pub)
- // modules2.rs
- // You can bring module paths into scopes and provide new names for them with the
- // 'use' and 'as' keywords. Fix these 'use' statements to make the code compile.
- // Execute `rustlings hint modules2` or use the `hint` watch subcommand for a hint.
-
- // I AM NOT DONE
-
- mod delicious_snacks {
- // TODO: Fix these use statements
- pub use self::fruits::PEAR as fruit;
- pub use self::veggies::CUCUMBER as veggie;
-
- mod fruits {
- pub const PEAR: &'static str = "Pear";
- pub const APPLE: &'static str = "Apple";
- }
-
- mod veggies {
- pub const CUCUMBER: &'static str = "Cucumber";
- pub const CARROT: &'static str = "Carrot";
- }
- }
-
- fn main() {
- println!(
- "favorite snacks: {} and {}",
- delicious_snacks::fruit,
- delicious_snacks::veggie
- );
- }
43.导入默认库的宏和库函数
- // modules3.rs
- // You can use the 'use' keyword to bring module paths from modules from anywhere
- // and especially from the Rust standard library into your scope.
- // Bring SystemTime and UNIX_EPOCH
- // from the std::time module. Bonus style points if you can do it with one line!
- // Execute `rustlings hint modules3` or use the `hint` watch subcommand for a hint.
-
- // I AM NOT DONE
-
- // TODO: Complete this use statement
- use std::time::SystemTime;
- use std::time::UNIX_EPOCH;
-
- fn main() {
- match SystemTime::now().duration_since(UNIX_EPOCH) {
- Ok(n) => println!("1970-01-01 00:00:00 UTC was {} seconds ago!", n.as_secs()),
- Err(_) => panic!("SystemTime before UNIX EPOCH!"),
- }
- }
44.new一个hashMap
HashMap::new()
注意末尾条件,添加足够种类和数量水果即可
- // hashmaps1.rs
- // A basket of fruits in the form of a hash map needs to be defined.
- // The key represents the name of the fruit and the value represents
- // how many of that particular fruit is in the basket. You have to put
- // at least three different types of fruits (e.g apple, banana, mango)
- // in the basket and the total count of all the fruits should be at
- // least five.
- //
- // Make me compile and pass the tests!
- //
- // Execute `rustlings hint hashmaps1` or use the `hint` watch subcommand for a hint.
-
- // I AM NOT DONE
-
- use std::collections::HashMap;
-
- fn fruit_basket() -> HashMap<String, u32> {
- let mut basket = HashMap::new();// TODO: declare your hash map here.
-
- // Two bananas are already given for you :)
- basket.insert(String::from("banana"), 2);
-
- // TODO: Put more fruits in your basket here.
-
- basket.insert("666".to_string(),3);
- basket.insert("999".to_string(),1);
- basket
- }
-
- #[cfg(test)]
- mod tests {
- use super::*;
-
- #[test]
- fn at_least_three_types_of_fruits() {
- let basket = fruit_basket();
- assert!(basket.len() >= 3);
- }
-
- #[test]
- fn at_least_five_fruits() {
- let basket = fruit_basket();
- assert!(basket.values().sum::<u32>() >= 5);
- }
- }
45.hashmap的基础插入操作
注意末尾测试的要求即可
- // hashmaps2.rs
-
- // A basket of fruits in the form of a hash map is given. The key
- // represents the name of the fruit and the value represents how many
- // of that particular fruit is in the basket. You have to put *MORE
- // THAN 11* fruits in the basket. Three types of fruits - Apple (4),
- // Mango (2) and Lychee (5) are already given in the basket. You are
- // not allowed to insert any more of these fruits!
- //
- // Make me pass the tests!
- //
- // Execute `rustlings hint hashmaps2` or use the `hint` watch subcommand for a hint.
-
- // I AM NOT DONE
-
- use std::collections::HashMap;
-
- #[derive(Hash, PartialEq, Eq)]
- enum Fruit {
- Apple,
- Banana,
- Mango,
- Lychee,
- Pineapple,
- }
-
- fn fruit_basket(basket: &mut HashMap
u32>) { - let fruit_kinds = vec![
- Fruit::Apple,
- Fruit::Banana,
- Fruit::Mango,
- Fruit::Lychee,
- Fruit::Pineapple,
- ];
-
- for fruit in fruit_kinds {
- // TODO: Put new fruits if not already present. Note that you
- // are not allowed to put any type of fruit that's already
- // present!
- }
- }
-
- #[cfg(test)]
- mod tests {
- use super::*;
-
- fn get_fruit_basket() -> HashMap
u32> { - let mut basket = HashMap::
u32>::new(); - basket.insert(Fruit::Apple, 4);
- basket.insert(Fruit::Mango, 2);
- basket.insert(Fruit::Lychee, 5);
- // at_least_five_types_of_fruits 种类>=5
- // greater_than_eleven_fruits 总数 >=1
- basket.insert(Fruit::Banana, 5);
- basket.insert(Fruit::Pineapple, 5);
- basket
- }
-
- #[test]
- fn test_given_fruits_are_not_modified() {
- let mut basket = get_fruit_basket();
- fruit_basket(&mut basket);
- assert_eq!(*basket.get(&Fruit::Apple).unwrap(), 4);
- assert_eq!(*basket.get(&Fruit::Mango).unwrap(), 2);
- assert_eq!(*basket.get(&Fruit::Lychee).unwrap(), 5);
- }
-
- #[test]
- fn at_least_five_types_of_fruits() {
- let mut basket = get_fruit_basket();
- fruit_basket(&mut basket);
- let count_fruit_kinds = basket.len();
- assert!(count_fruit_kinds >= 5);
- }
-
- #[test]
- fn greater_than_eleven_fruits() {
- let mut basket = get_fruit_basket();
- fruit_basket(&mut basket);
- let count = basket.values().sum::<u32>();
- assert!(count > 11);
- }
- }
46.查看hashmap是否包含某个键
这一题有点综合性难度了,我们需要对每场比赛的双方统计得球和失球的次数,然后通过hashMap传递出去
- // hashmaps3.rs
-
- // A list of scores (one per line) of a soccer match is given. Each line
- // is of the form :
- //
,,, - // Example: England,France,4,2 (England scored 4 goals, France 2).
-
- // You have to build a scores table containing the name of the team, goals
- // the team scored, and goals the team conceded. One approach to build
- // the scores table is to use a Hashmap. The solution is partially
- // written to use a Hashmap, complete it to pass the test.
-
- // Make me pass the tests!
-
- // Execute `rustlings hint hashmaps3` or use the `hint` watch subcommand for a hint.
-
- // I AM NOT DONE
-
- use std::collections::HashMap;
-
- // A structure to store team name and its goal details.
- struct Team {
- name: String,
- goals_scored: u8,
- goals_conceded: u8,
- }
-
- fn build_scores_table(results: String) -> HashMap<String, Team> {
- // The name of the team is the key and its associated struct is the value.
- let mut scores: HashMap<String, Team> = HashMap::new();
-
- for r in results.lines() {
- let v: Vec<&str> = r.split(',').collect();
- let team_1_name = v[0].to_string();
- let team_1_score: u8 = v[2].parse().unwrap();
- let team_2_name = v[1].to_string();
- let team_2_score: u8 = v[3].parse().unwrap();
- // TODO: Populate the scores table with details extracted from the
- // current line. Keep in mind that goals scored by team_1
- // will be number of goals conceded from team_2, and similarly
- // goals scored by team_2 will be the number of goals conceded by
- // team_1.
- if !scores.contains_key(&team_1_name) {
- // 创建新用户 都初始化为0
- scores.insert(team_1_name.clone(),Team{
- name: team_1_name.clone(),
- goals_scored: 0,
- goals_conceded: 0,
- });
- };
- if !scores.contains_key(&team_2_name) {
- // 创建新用户 都初始化为0
- scores.insert(team_2_name.clone(),Team{
- name: team_2_name.clone(),
- goals_scored: 0,
- goals_conceded: 0,
- });
- };
- let team1=scores.get_mut(&team_1_name).unwrap();
- team1.goals_scored+=team_1_score;
- team1.goals_conceded+=team_2_score;
-
- let team2=scores.get_mut(&team_2_name).unwrap();
- team2.goals_scored+=team_2_score;
- team2.goals_conceded+=team_1_score;
-
- }
- scores
- }
-
- #[cfg(test)]
- mod tests {
- use super::*;
-
- fn get_results() -> String {
- let results = "".to_string()
- + "England,France,4,2\n"
- + "France,Italy,3,1\n"
- + "Poland,Spain,2,0\n"
- + "Germany,England,2,1\n";
- results
- }
-
- #[test]
- fn build_scores() {
- let scores = build_scores_table(get_results());
-
- let mut keys: Vec<&String> = scores.keys().collect();
- keys.sort();
- assert_eq!(
- keys,
- vec!["England", "France", "Germany", "Italy", "Poland", "Spain"]
- );
- }
-
- #[test]
- fn validate_team_score_1() {
- let scores = build_scores_table(get_results());
- let team = scores.get("England").unwrap();
- assert_eq!(team.goals_scored, 5);
- assert_eq!(team.goals_conceded, 4);
- }
-
- #[test]
- fn validate_team_score_2() {
- let scores = build_scores_table(get_results());
- let team = scores.get("Spain").unwrap();
- assert_eq!(team.goals_scored, 0);
- assert_eq!(team.goals_conceded, 2);
- }
- }
47.match通配和转大写/去空白字符/重复添加字符串
对于这样的一个变量
- let output = transformer(vec![
- ("hello".into(), Command::Uppercase),
- (" all roads lead to rome! ".into(), Command::Trim),
- ("foo".into(), Command::Append(1)),
- ("bar".into(), Command::Append(5)),
- ]);
我们需要使用如下形式来定义
Vec<(String,Command)
其中,枚举类型结构如下
- pub enum Command {
- Uppercase,
- Trim,
- Append(usize),
- }
将字符串转大写 to_uppercase()
output.push(string.to_uppercase())
将字符串首尾空白字符去除
output.push(string.trim().to_string())
在字符串末尾重复添加特定字符串
output.push(string.to_string()+&"bar".to_string().repeat(*nums))
然后导入my_moduleghegmod里面的公共方法transformer到test里面去即可
- // quiz2.rs
- // This is a quiz for the following sections:
- // - Strings
- // - Vecs
- // - Move semantics
- // - Modules
- // - Enums
-
- // Let's build a little machine in form of a function.
- // As input, we're going to give a list of strings and commands. These commands
- // determine what action is going to be applied to the string. It can either be:
- // - Uppercase the string
- // - Trim the string
- // - Append "bar" to the string a specified amount of times
- // The exact form of this will be:
- // - The input is going to be a Vector of a 2-length tuple,
- // the first element is the string, the second one is the command.
- // - The output element is going to be a Vector of strings.
- // No hints this time!
-
- // I AM NOT DONE
-
- pub enum Command {
- Uppercase,
- Trim,
- Append(usize),
- }
-
- mod my_module {
- use super::Command;
-
- // TODO: Complete the function signature!
- pub fn transformer(input: Vec<(String,Command)>) -> Vec<String> {
- // TODO: Complete the output declaration!
- let mut output: Vec<String> = vec![];
- for (string, command) in input.iter() {
- // TODO: Complete the function body. You can do it!
- match command {
- Command::Uppercase => {
- output.push(string.to_uppercase())
- }
- Command::Trim => {
- output.push(string.trim().to_string())
- }
- Command::Append(nums) =>{
- output.push(string.to_string()+&"bar".to_string().repeat(*nums))
- }
- }
- }
- output
- }
- }
-
- #[cfg(test)]
- mod tests {
- // TODO: What do we have to import to have `transformer` in scope?
- use my_module::transformer;
- use super::Command;
-
- #[test]
- fn it_works() {
- let output = transformer(vec![
- ("hello".into(), Command::Uppercase),
- (" all roads lead to rome! ".into(), Command::Trim),
- ("foo".into(), Command::Append(1)),
- ("bar".into(), Command::Append(5)),
- ]);
- assert_eq!(output[0], "HELLO");
- assert_eq!(output[1], "all roads lead to rome!");
- assert_eq!(output[2], "foobar");
- assert_eq!(output[3], "barbarbarbarbarbar");
- }
- }
48.根据小时来获取冰淇淋的数量
我们首先得知道Option
我们有两个任务
(1)填补时辰和冰淇淋数量的逻辑关系并对错误的时辰进行特判
(2)对错误的测试样例进行类型修正
我们填写以下逻辑
- fn maybe_icecream(time_of_day: u16) -> Option<u16> {
- // We use the 24-hour system here, so 10PM is a value of 22 and 12AM is a value of 0
- // The Option output should gracefully handle cases where time_of_day > 23.
- if (time_of_day<=12) {
- Some(5)
- }
- else if (time_of_day<=24) {
- Some(0)
- }
- else{
- None
- }
- }
并修改测试样 raw_value的值判断为即可
assert_eq!(icecreams, Some(5));
- // options1.rs
- // Execute `rustlings hint options1` or use the `hint` watch subcommand for a hint.
-
- // I AM NOT DONE
-
- // This function returns how much icecream there is left in the fridge.
- // If it's before 10PM, there's 5 pieces left. At 10PM, someone eats them
- // all, so there'll be no more left :(
- // TODO: Return an Option!
- fn maybe_icecream(time_of_day: u16) -> Option<u16> {
- // We use the 24-hour system here, so 10PM is a value of 22 and 12AM is a value of 0
- // The Option output should gracefully handle cases where time_of_day > 23.
- if (time_of_day<=12) {
- Some(5)
- }
- else if (time_of_day<=24) {
- Some(0)
- }
- else{
- None
- }
- }
-
- #[cfg(test)]
- mod tests {
- use super::*;
-
- #[test]
- fn check_icecream() {
- assert_eq!(maybe_icecream(9), Some(5));
- assert_eq!(maybe_icecream(10), Some(5));
- assert_eq!(maybe_icecream(23), Some(0));
- assert_eq!(maybe_icecream(22), Some(0));
- assert_eq!(maybe_icecream(25), None);
- }
-
- #[test]
- fn raw_value() {
- // TODO: Fix this test. How do you get at the value contained in the Option?
- let icecreams = maybe_icecream(12);
- assert_eq!(icecreams, Some(5));
- }
- }
48.let type(A)=unknowType(value)的使用
这里面有两个关键语句
let Some(word) = optional_target
let Some(Some(integer)) = optional_integers.pop()
他们的意思是如果等式两边类型相等,
那么就将等式右边的值赋值给等式左边的括号里面的变量
其可以配合if和while使用 ,也可以使用花括号对后续进行操作
- // options2.rs
- // Execute `rustlings hint options2` or use the `hint` watch subcommand for a hint.
-
- // I AM NOT DONE
-
- #[cfg(test)]
- mod tests {
- use super::*;
-
- #[test]
- fn simple_option() {
- let target = "rustlings";
- let optional_target = Some(target);
-
- // TODO: Make this an if let statement whose value is "Some" type
- if let Some(word) = optional_target {
- assert_eq!(word, target);
- }
- }
-
- #[test]
- fn layered_option() {
- let mut range = 10;
- let mut optional_integers: Vec<Option<i8>> = Vec::new();
- for i in 0..(range + 1) {
- optional_integers.push(Some(i));
- }
-
- // TODO: make this a while let statement - remember that vector.pop also adds another layer of Option
- // You can stack `Option
`'s into while let and if let - while let Some(Some(integer)) = optional_integers.pop() {
- assert_eq!(integer, range);
- range -= 1;
- }
- }
- }
49.将引用传递给match避免产生所有权转让
- // options3.rs
- // Execute `rustlings hint options3` or use the `hint` watch subcommand for a hint.
-
- // I AM NOT DONE
-
- struct Point {
- x: i32,
- y: i32,
- }
-
- fn main() {
- let y: Option
= Some(Point { x: 100, y: 200 }); -
- match &y {
- Some(p) => println!("Co-ordinates are {},{} ", p.x, p.y),
- _ => println!("no match"),
- }
- y; // Fix without deleting this line.
- }
50.错误类型处理
处理事物错误与否,我们要使用Result
其包含Ok(value)和Err(value)这两种枚举
Result
- // errors1.rs
- // This function refuses to generate text to be printed on a nametag if
- // you pass it an empty string. It'd be nicer if it explained what the problem
- // was, instead of just sometimes returning `None`. Thankfully, Rust has a similar
- // construct to `Option` that can be used to express error conditions. Let's use it!
- // Execute `rustlings hint errors1` or use the `hint` watch subcommand for a hint.
-
- // I AM NOT DONE
-
- pub fn generate_nametag_text(name: String) -> Result<String,String> {
- if name.is_empty() {
- // Empty names aren't allowed.
- // None
- Err("`name` was empty; it must be nonempty.".into())
- } else {
- Ok(format!("Hi! My name is {}", name))
- }
- }
-
- #[cfg(test)]
- mod tests {
- use super::*;
-
- #[test]
- fn generates_nametag_text_for_a_nonempty_name() {
- assert_eq!(
- generate_nametag_text("Beyoncé".into()),
- Ok("Hi! My name is Beyoncé".into())
- );
- }
-
- #[test]
- fn explains_why_generating_nametag_text_fails() {
- assert_eq!(
- generate_nametag_text("".into()),
- // Don't change this line
- Err("`name` was empty; it must be nonempty.".into())
- );
- }
- }