Generic Stack
Part of the Object Oriented Programming section of Coddy's Rust journey — lesson 59 of 61.
Challenge
EasyA stack is a fundamental data structure that follows the "Last In, First Out" (LIFO) principle—the last item added is the first one removed. Think of a stack of plates: you add plates to the top and remove them from the top.
Let's build a generic Stack data structure that can hold any type of element! A stack follows the "Last In, First Out" principle—like a stack of books where you can only add or remove from the top.
You'll organize your code across two files:
stack.rs: Define your genericStack<T>struct that uses aVec<T>internally to store elements. Implement three methods:newto create an empty stack,pushto add an element to the top, andpopto remove and return the top element (returningOption<T>since the stack might be empty).main.rs: Bring in your stack module and demonstrate your Stack working with integers. Create a stack, push the provided numbers onto it, then pop elements off and print each one. Useunwrap_orto handle theOptionreturned by pop—if the stack is empty, use-1as the default value.
A stack needs two essential operations:
- push — adds an element to the top of the stack
- pop — removes and returns the top element
The pop method should return an Option<T> since the stack might be empty. The Vec type already has a pop method that returns Option<T>, which you can leverage in your implementation.
Your stack should work like this: when you push values 10, 20, and 30 (in that order), popping three times should give you 30, 20, and 10 (reverse order). A fourth pop on an empty stack should return the default value.
Print each popped value on its own line:
30
20
10
-1For example, with inputs 5, 15, and 25:
25
15
5
-1You will receive three inputs: three integers to push onto the stack (parse each as i32). After pushing all three, pop four times to demonstrate both successful pops and the empty stack case.
Try it yourself
mod stack;
use stack::Stack;
fn main() {
// Read three integers from input
let mut input1 = String::new();
std::io::stdin().read_line(&mut input1).expect("Failed to read line");
let num1: i32 = input1.trim().parse().expect("Invalid number");
let mut input2 = String::new();
std::io::stdin().read_line(&mut input2).expect("Failed to read line");
let num2: i32 = input2.trim().parse().expect("Invalid number");
let mut input3 = String::new();
std::io::stdin().read_line(&mut input3).expect("Failed to read line");
let num3: i32 = input3.trim().parse().expect("Invalid number");
// TODO: Create a new Stack
// TODO: Push the three numbers onto the stack (num1, num2, num3 in that order)
// TODO: Pop four times and print each result
// Use unwrap_or(-1) to handle the empty stack case
}
All lessons in Object Oriented Programming
1Methods and Behavior
Intro Implementation BlocksThe Self ParameterMutable MethodsAssociated FunctionsMultiple Implementation BlocksMethod ChainingRecap - Rectangle Actions4Project: Virtual Pet
Defining the PetFeeding the Pet7Standard Traits
The Debug TraitThe Display TraitClone and CopyEquality TraitsRecap - Printable Point10Project: Document System
The Draw TraitText Component2Encapsulation and Modules
Modules BasicsThe Public KeywordPrivate FieldsGettersSettersRecap - Secure Locker5Generics
Generic StructsGeneric MethodsMultiple Generic TypesGeneric FunctionsRecap - Coordinate Point8Traits as Bounds
Trait Bounds SyntaxMultiple BoundsThe Where ClauseReturning Types with TraitsRecap - Generic Printer11Design Patterns in Rust
Newtype PatternCompositionThe Drop TraitFrom and IntoRecap - Smart Pointer Mock