9.15 Exercises

  1. Defining and Using a Struct

    Define a Rectangle struct with width and height fields. Implement methods to calculate the area and perimeter.

    struct Rectangle {
        width: u32,
        height: u32,
    }
    
    impl Rectangle {
        fn area(&self) -> u32 {
            self.width * self.height
        }
    
        fn perimeter(&self) -> u32 {
            2 * (self.width + self.height)
        }
    }
    
    fn main() {
        let rect = Rectangle { width: 10, height: 20 };
        println!("Area: {}", rect.area());
        println!("Perimeter: {}", rect.perimeter());
    }
  2. Generic Struct

    Create a generic Pair struct that holds two values of any type. Implement a method to return a reference to the first value.

    struct Pair<T, U> {
        first: T,
        second: U,
    }
    
    impl<T, U> Pair<T, U> {
        fn first(&self) -> &T {
            &self.first
        }
    }
    
    fn main() {
        let pair = Pair { first: "Hello", second: 42 };
        println!("First: {}", pair.first());
    }
  3. Struct with References and Lifetimes

    Define a Book struct that holds references to title and author. Ensure that lifetimes are handled correctly.

    struct Book<'a> {
        title: &'a str,
        author: &'a str,
    }
    
    fn main() {
        let title = String::from("Rust Programming");
        let author = String::from("John Doe");
    
        let book = Book {
            title: &title,
            author: &author,
        };
    
        println!("{} by {}", book.title, book.author);
    }
  4. Implementing Traits

    Derive the Debug and PartialEq traits for a Point struct. Create instances and compare them.

    #[derive(Debug, PartialEq)]
    struct Point {
        x: i32,
        y: i32,
    }
    
    fn main() {
        let p1 = Point { x: 1, y: 2 };
        let p2 = Point { x: 1, y: 2 };
    
        println!("{:?}", p1);
        println!("Points are equal: {}", p1 == p2);
    }
  5. Method Consuming Self

    Implement a method for Person that consumes the instance and returns the name.

    struct Person {
        name: String,
        age: u8,
    }
    
    impl Person {
        fn into_name(self) -> String {
            self.name
        }
    }
    
    fn main() {
        let person = Person { name: String::from("Ivy"), age: 29 };
        let name = person.into_name();
        println!("Name: {}", name);
        // person can no longer be used here
    }