diff --git a/.rustlings-state.txt b/.rustlings-state.txt index 64e0b71..fd19189 100644 --- a/.rustlings-state.txt +++ b/.rustlings-state.txt @@ -1,6 +1,6 @@ DON'T EDIT THIS FILE! -strings1 +modules1 intro1 intro2 @@ -38,4 +38,8 @@ structs3 enums1 enums2 enums3 +strings1 +strings2 +strings3 +strings4 quiz2 \ No newline at end of file diff --git a/exercises/09_strings/strings2.rs b/exercises/09_strings/strings2.rs index 93d9cb6..9e605a6 100644 --- a/exercises/09_strings/strings2.rs +++ b/exercises/09_strings/strings2.rs @@ -6,7 +6,7 @@ fn is_a_color_word(attempt: &str) -> bool { fn main() { let word = String::from("green"); // Don't change this line. - if is_a_color_word(word) { + if is_a_color_word(word.as_str()) { println!("That is a color word I know!"); } else { println!("That is not a color word I know."); diff --git a/exercises/09_strings/strings3.rs b/exercises/09_strings/strings3.rs index f5e45b0..c293005 100644 --- a/exercises/09_strings/strings3.rs +++ b/exercises/09_strings/strings3.rs @@ -1,13 +1,26 @@ fn trim_me(input: &str) -> &str { - // TODO: Remove whitespace from both ends of a string. + // TODO: Remove whitespace from both ends of a string + // can find the 1st not whitespace and last not whitespace and then return slice + let f = input + .find(|c: char| !c.is_whitespace()) + .unwrap_or(input.len()); + let r = input.rfind(|c: char| !c.is_whitespace()).unwrap_or(0); + if f < r { + &input[f..r + 1] + } else { + &input[..input.len() - f] + } + // input.trim() } fn compose_me(input: &str) -> String { // TODO: Add " world!" to the string! There are multiple ways to do this. + input.to_owned() + " world!" } fn replace_me(input: &str) -> String { // TODO: Replace "cars" in the string with "balloons". + input.to_owned().replace("cars", "balloons") } fn main() { @@ -20,6 +33,7 @@ mod tests { #[test] fn trim_a_string() { + assert_eq!(trim_me(" "), ""); assert_eq!(trim_me("Hello! "), "Hello!"); assert_eq!(trim_me(" What's up!"), "What's up!"); assert_eq!(trim_me(" Hola! "), "Hola!"); diff --git a/exercises/09_strings/strings4.rs b/exercises/09_strings/strings4.rs index 4730726..ae7599e 100644 --- a/exercises/09_strings/strings4.rs +++ b/exercises/09_strings/strings4.rs @@ -1,5 +1,5 @@ // Calls of this function should be replaced with calls of `string_slice` or `string`. -fn placeholder() {} +fn placeholder(_input: String) {} fn string_slice(arg: &str) { println!("{arg}"); @@ -13,7 +13,7 @@ fn string(arg: String) { // Your task is to replace `placeholder(…)` with either `string_slice(…)` // or `string(…)` depending on what you think each value is. fn main() { - placeholder("blue"); + string_slice("blue"); placeholder("red".to_string()); @@ -27,9 +27,9 @@ fn main() { // WARNING: This is byte indexing, not character indexing. // Character indexing can be done using `s.chars().nth(INDEX)`. - placeholder(&String::from("abc")[0..1]); + placeholder(String::from("abc")[0..1].to_string()); - placeholder(" hello there ".trim()); + placeholder(" hello there ".trim().to_string()); placeholder("Happy Monday!".replace("Mon", "Tues")); diff --git a/solutions/09_strings/strings3.rs b/solutions/09_strings/strings3.rs index dcf2377..ee6b56a 100644 --- a/solutions/09_strings/strings3.rs +++ b/solutions/09_strings/strings3.rs @@ -1,4 +1,49 @@ -fn main() { - // DON'T EDIT THIS SOLUTION FILE! - // It will be automatically filled after you finish the exercise. +fn trim_me(input: &str) -> &str { + input.trim() +} + +fn compose_me(input: &str) -> String { + // The macro `format!` has the same syntax as `println!`, but it returns a + // string instead of printing it to the terminal. + // Equivalent to `input.to_string() + " world!"` + format!("{input} world!") +} + +fn replace_me(input: &str) -> String { + input.replace("cars", "balloons") +} + +fn main() { + // You can optionally experiment here. +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn trim_a_string() { + assert_eq!(trim_me("Hello! "), "Hello!"); + assert_eq!(trim_me(" What's up!"), "What's up!"); + assert_eq!(trim_me(" Hola! "), "Hola!"); + assert_eq!(trim_me("Hi!"), "Hi!"); + } + + #[test] + fn compose_a_string() { + assert_eq!(compose_me("Hello"), "Hello world!"); + assert_eq!(compose_me("Goodbye"), "Goodbye world!"); + } + + #[test] + fn replace_a_string() { + assert_eq!( + replace_me("I think cars are cool"), + "I think balloons are cool", + ); + assert_eq!( + replace_me("I love to look at cars"), + "I love to look at balloons", + ); + } } diff --git a/solutions/09_strings/strings4.rs b/solutions/09_strings/strings4.rs index dcf2377..3c69b97 100644 --- a/solutions/09_strings/strings4.rs +++ b/solutions/09_strings/strings4.rs @@ -1,4 +1,38 @@ -fn main() { - // DON'T EDIT THIS SOLUTION FILE! - // It will be automatically filled after you finish the exercise. +fn string_slice(arg: &str) { + println!("{arg}"); +} + +fn string(arg: String) { + println!("{arg}"); +} + +fn main() { + string_slice("blue"); + + string("red".to_string()); + + string(String::from("hi")); + + string("rust is fun!".to_owned()); + + // Here, both answers work. + // `.into()` converts a type into an expected type. + // If it is called where `String` is expected, it will convert `&str` to `String`. + string("nice weather".into()); + // But if it is called where `&str` is expected, then `&str` is kept `&str` since no conversion is needed. + // If you remove the `#[allow(…)]` line, then Clippy will tell you to remove `.into()` below since it is a useless conversion. + #[allow(clippy::useless_conversion)] + string_slice("nice weather".into()); + + string(format!("Interpolation {}", "Station")); + + // WARNING: This is byte indexing, not character indexing. + // Character indexing can be done using `s.chars().nth(INDEX)`. + string_slice(&String::from("abc")[0..1]); + + string_slice(" hello there ".trim()); + + string("Happy Monday!".replace("Mon", "Tues")); + + string("mY sHiFt KeY iS sTiCkY".to_lowercase()); }