Pair Programming IDE Rust
👤 Sharing: AI
```rust
use std::io;
// Define a struct to represent a task
#[derive(Debug)]
struct Task {
description: String,
completed: bool,
}
impl Task {
// Constructor for a new task
fn new(description: String) -> Task {
Task {
description,
completed: false,
}
}
// Method to mark a task as completed
fn mark_completed(&mut self) {
self.completed = true;
}
}
fn main() {
// Initialize a vector to store tasks
let mut tasks: Vec<Task> = Vec::new();
loop {
// Display the menu
println!("\nTask Manager");
println!("1. Add task");
println!("2. List tasks");
println!("3. Mark task as completed");
println!("4. Exit");
// Get user input
let mut choice = String::new();
println!("Enter your choice: ");
io::stdin()
.read_line(&mut choice)
.expect("Failed to read line");
// Parse the user's choice
let choice: u32 = match choice.trim().parse() {
Ok(num) => num,
Err(_) => {
println!("Invalid input. Please enter a number.");
continue;
}
};
// Process the user's choice
match choice {
1 => {
// Add a new task
println!("Enter task description: ");
let mut description = String::new();
io::stdin()
.read_line(&mut description)
.expect("Failed to read line");
let description = description.trim().to_string(); // Remove leading/trailing whitespace
let new_task = Task::new(description);
tasks.push(new_task);
println!("Task added!");
}
2 => {
// List tasks
if tasks.is_empty() {
println!("No tasks yet!");
} else {
println!("Tasks:");
for (index, task) in tasks.iter().enumerate() {
println!(
"{}. {} (Completed: {})",
index + 1,
task.description,
task.completed
);
}
}
}
3 => {
// Mark a task as completed
println!("Enter the task number to mark as completed: ");
let mut task_number = String::new();
io::stdin()
.read_line(&mut task_number)
.expect("Failed to read line");
let task_number: usize = match task_number.trim().parse() {
Ok(num) => num,
Err(_) => {
println!("Invalid input. Please enter a number.");
continue;
}
};
// Check if the task number is valid
if task_number > 0 && task_number <= tasks.len() {
let task_index = task_number - 1;
tasks[task_index].mark_completed();
println!("Task marked as completed!");
} else {
println!("Invalid task number.");
}
}
4 => {
// Exit the program
println!("Exiting...");
break;
}
_ => {
println!("Invalid choice. Please enter a number between 1 and 4.");
}
}
}
}
```
**Explanation:**
1. **`use std::io;`**: This line imports the `io` module from the standard library, which is needed for input/output operations (like reading from the console).
2. **`struct Task`**: This defines a `struct` called `Task`. A `struct` is a custom data type that groups related data together. In this case, each `Task` has:
- `description`: A `String` representing the task's description (e.g., "Buy groceries").
- `completed`: A `bool` indicating whether the task has been completed (true) or not (false).
3. **`impl Task`**: This block implements methods for the `Task` struct. Methods are functions associated with a particular type.
- **`fn new(description: String) -> Task`**: This is a constructor function. It takes a task description as input and returns a new `Task` instance. It initializes the `completed` field to `false` by default.
- **`fn mark_completed(&mut self)`**: This method allows you to mark a task as completed. The `&mut self` parameter means it takes a mutable reference to the `Task` instance, allowing it to modify the `completed` field.
4. **`fn main()`**: This is the main function, the entry point of the program.
5. **`let mut tasks: Vec<Task> = Vec::new();`**: This line creates a mutable vector (a dynamically sized array) called `tasks`. It will store `Task` structs. `Vec::new()` initializes an empty vector. The `mut` keyword is crucial because we'll be adding, removing, and modifying tasks in the vector.
6. **`loop { ... }`**: This creates an infinite loop that continues until the user chooses to exit.
7. **Menu Display**: Inside the loop, the program displays a menu with options for adding, listing, marking completed, and exiting.
8. **User Input**:
- `io::stdin().read_line(&mut choice)`: This reads a line of text from the standard input (the console) and stores it in the `choice` string. The `&mut choice` part passes a mutable reference to the `choice` string, so the `read_line` function can modify it.
- **Error Handling**: `expect("Failed to read line")`: This handles potential errors during the input process. If `read_line` fails (e.g., due to an unexpected error), the program will panic and display the error message.
- **Parsing Input**: `choice.trim().parse()`: This part converts the user's input (which is a string) into a number (u32).
- `trim()`: Removes any leading or trailing whitespace from the input string.
- `parse()`: Attempts to parse the string as a `u32` (unsigned 32-bit integer). The `parse()` method returns a `Result` type, which can be either `Ok(value)` if the parsing was successful or `Err(error)` if it failed.
- **Matching the Result**: `match choice.trim().parse() { ... }`: This uses a `match` expression to handle the result of the parsing operation.
- `Ok(num) => num`: If the parsing was successful, the `Ok` variant contains the parsed number (num), which is then assigned to the `choice` variable.
- `Err(_) => { ... }`: If the parsing failed (e.g., the user entered text that wasn't a number), the `Err` variant is matched. The `_` is a wildcard pattern that matches any error value. An error message is printed, and the `continue` statement skips to the next iteration of the loop.
9. **Processing User Choice**: The `match choice { ... }` expression processes the user's choice.
10. **Adding a Task (Choice 1)**:
- Prompts the user for the task description.
- Reads the description from the console.
- Creates a new `Task` instance using `Task::new()`.
- Adds the new task to the `tasks` vector using `tasks.push()`.
11. **Listing Tasks (Choice 2)**:
- Checks if the `tasks` vector is empty. If so, it prints a message saying "No tasks yet!".
- If there are tasks, it iterates through the `tasks` vector using a `for` loop with `enumerate()`. `enumerate()` provides both the index and the value of each element in the vector.
- Prints the task number (index + 1), description, and completion status for each task.
12. **Marking a Task as Completed (Choice 3)**:
- Prompts the user to enter the task number to mark as completed.
- Reads the task number from the console.
- Parses the input as a `usize` (unsigned integer, suitable for indexing).
- **Input Validation**: Checks if the entered task number is valid (i.e., within the range of valid task indices).
- Accesses the task at the specified index using `tasks[task_index]`.
- Calls the `mark_completed()` method on the task to set its `completed` field to `true`.
13. **Exiting (Choice 4)**:
- Prints an "Exiting..." message.
- `break;` exits the loop, ending the program.
14. **Invalid Choice**: If the user enters an invalid choice (other than 1-4), an error message is printed.
**How to Compile and Run:**
1. **Install Rust:** If you haven't already, install Rust from [https://www.rust-lang.org/tools/install](https://www.rust-lang.org/tools/install).
2. **Save the Code:** Save the code as a `.rs` file (e.g., `task_manager.rs`).
3. **Compile:** Open a terminal or command prompt and navigate to the directory where you saved the file. Then, compile the code using the Rust compiler:
```bash
rustc task_manager.rs
```
4. **Run:** After successful compilation, an executable file will be created (e.g., `task_manager` on Linux/macOS or `task_manager.exe` on Windows). Run the executable:
```bash
./task_manager # Linux/macOS
task_manager.exe # Windows
```
Now you can interact with the task manager program in your terminal.
👁️ Viewed: 5
Comments