Hone logo
Hone
Problems

Mastering Rust Ownership: A String Manipulation Challenge

Rust's ownership system is a cornerstone of its memory safety guarantees. This challenge will guide you through fundamental concepts of ownership, borrowing, and how they apply to manipulating strings. Understanding these basics is crucial for writing safe and efficient Rust code.

Problem Description

Your task is to implement a Rust function that takes a String as input and performs a series of transformations. You will need to demonstrate your understanding of ownership transfer and immutable borrowing. Specifically, you will:

  1. Create a function that accepts a String.
  2. Inside the function, print the original string without consuming it.
  3. Return a new String that is a modified version of the input string.
  4. Ensure the original String remains usable after the function call.

Examples

Example 1:

Input: A mutable String named `greeting` with the value "Hello".

// In main function:
let mut greeting = String::from("Hello");
let modified_greeting = process_string(greeting);
println!("Original greeting after processing: {}", greeting); // Should print "Hello"
println!("Modified greeting: {}", modified_greeting); // Should print "Hello, world!"

// Function definition:
fn process_string(s: String) -> String {
    // ... implementation ...
}
Output:
Original greeting after processing: Hello
Modified greeting: Hello, world!

Explanation: The process_string function takes ownership of the String. Inside the function, we print it, then create a new String by appending ", world!". The crucial part is that the original greeting variable in main should still be valid and accessible because the function process_string consumes its input. To achieve the expected output, the function must return a new string, not modify the input in place if the intent is to keep the original usable. Correction: The prompt implies the original String should be usable, which means the function should ideally not take ownership if it needs to be used later, or the ownership transfer needs careful handling to ensure the original variable is still in scope and valid. Let's refine the problem to focus on immutable borrowing for printing and then returning a new string.

Revised Example 1:

Input: A String named `message` with the value "Rust is cool".

// In main function:
let message = String::from("Rust is cool");
let processed = modify_and_extend(message.clone()); // Clone to allow original to be used
println!("Original message: {}", message); // Should print "Rust is cool"
println!("Processed message: {}", processed); // Should print "Rust is cool and safe"

// Function definition:
fn modify_and_extend(s: String) -> String {
    // ... implementation ...
}
Output:
Original message: Rust is cool
Processed message: Rust is cool and safe

Explanation: The modify_and_extend function receives ownership of a cloned String. It then creates and returns a new String by appending " and safe". The original message in main remains untouched because we passed a clone to the function, effectively transferring ownership of the clone.

Example 2:

Input: A String named `name` with the value "Alice".

// In main function:
let name = String::from("Alice");
let greeting = greet_user(name.clone());
println!("Original name: {}", name); // Should print "Alice"
println!("Greeting: {}", greeting); // Should print "Hello, Alice!"

// Function definition:
fn greet_user(user_name: String) -> String {
    // ... implementation ...
}
Output:
Original name: Alice
Greeting: Hello, Alice!

Explanation: The greet_user function takes ownership of a cloned String representing a user's name. It constructs a new String by prepending "Hello, " and appending "!". The original name variable is still valid.

Constraints

  • The input to your primary processing function will always be a String.
  • The output of your primary processing function will always be a String.
  • You must demonstrate the ability to not consume the original String when performing an operation that conceptually "uses" it (like printing).

Notes

  • Consider how clone() can be used to create a new owned value from an existing one, allowing the original to remain in scope.
  • Think about how you can borrow a string immutably to print its contents without taking ownership.
  • The goal is to have the original String variable remain valid and accessible after the function has been called and has returned its result.
  • You might need to create helper functions to demonstrate different aspects of ownership and borrowing.
Loading editor...
rust