4.6 KiB
Rust Übungsaufagaben:
1. Ownership & Borrowing:
Aufgabe 1:
Erkläre, warum folgender Rust-Code nicht kompiliert:
fn main() {
let s1 = String::from("Hallo");
let s2 = s1;
println!("{}", s1);
}
Ändere den Code so, dass s1 und s2 augegeben werden können.
Aufgabe 2:
Warum verbietet Rust folgenden Code?
fn main() {
let mut text = String::from("Rust");
let r1 = &text;
let r2 = &mut text;
println!("{}", r1);
println!("{}", r2);
}
Schreibe den Code so um, sodass beide println! statements funktionieren.
2. Pattern Matching & Enums:
Aufgabe 3:
Gegeben sei folgender Rust Code für eine 3-Phasen Ampel:
fn main(){
enum Ampel {
Rot,
Gelb,
Gruen,
}
let ampel_status = Ampel::Rot;
match ampel_status {
Ampel::Rot => println!("STOP"),
Ampel::Gelb => println!("Achtung"),
Ampel::Gruen => println!("fahren"),
}
}
Ändere den Code in match ampel_status so ab, dass auch in Ampel beliebig viele andere Farben als Fahrsignal genutzt werden können.
Was passiert wenn nicht alle Varainten in match ampel_status aufgelistet werden?
3. Option & Result Types:
Aufgabe 4:
Erkläre, warum folgender Code nicht funktioniert und behebe das Problem:
fn main() {
let numbers = vec![1, 2, 3, 4, 5];
let index = 10;
let value = numbers[index];
println!("Wert: {}", value);
}
Verwende Option oder eine andere Fehlerbehandlung, um sicher auf den Vektor zuzugreifen. Erkläre die Vorteile dieses Ansatzes gegenüber einem Laufzeitfehler ("panic").
Aufgabe 5:
Schreibe eine Funktion parse_number, die einen String nimmt und ein Result<i32, String> zurückgibt:
- Bei erfolgreicher Konvertierung:
Ok(zahl) - Bei Fehler:
Err("Ungültige Eingabe".to_string())
Verwende danach die Funktion in main() und behandle das Result mit match.
fn parse_number(input: &str) -> Result<i32, String> {
// TODO: Implementierung
}
fn main() {
// TODO: Funktion testen und Error Handling
}
Wie unterscheidet sich Result von Option? Wann verwendet man welchen Typ?
4. String vs &str und Ownership:
Aufgabe 6:
Erkläre den Unterschied zwischen String und &str. Warum verbietet Rust folgende Funktion zu kompilieren?
fn greet(name: &str) {
println!("Hallo, {}!", name);
}
fn main() {
let my_string = String::from("Alice");
let string_slice = "Bob";
greet(my_string); // Fehler?
greet(string_slice);
}
Behebe den Fehler und erkläre, warum die Verwendung von &str als Parameter flexibler ist.
Aufgabe 7:
Was ist der Unterschied zwischen folgenden zwei Funktionen? Welche ist besser und warum?
// Variante 1:
fn create_greeting_1(name: String) -> String {
format!("Hallo, {}!", name)
}
// Variante 2:
fn create_greeting_2(name: &str) -> String {
format!("Hallo, {}!", name)
}
Schreibe für beide Varianten ein Beispiel in main(), das die Flexibilität von Variante 2 demonstriert.
5. Traits und Polymorphismus:
Aufgabe 8:
Gegeben sind folgende Structs und ein Trait:
struct Kreis {
radius: f64,
}
struct Rechteck {
width: f64,
height: f64,
}
trait Flaeche {
fn flaeche(&self) -> f64;
}
Implementiere den Flaeche Trait für beide Structs. Schreibe dann eine Funktion, die eine Referenz auf ein Objekt mit Flaeche Trait annimmt und dessen Fläche ausgibt.
Bonus: Erstelle einen Vektor mit verschiedenen Formen und iteriere über sie.
6. Mutability und Interior Mutability:
Aufgabe 9:
Erkläre, warum folgender Code nicht funktioniert:
fn main() {
let counter = 0;
counter += 1;
println!("Counter: {}", counter);
}
Wie würde man diesen Code korrekt schreiben? Was ist der Unterschied zwischen let mut und Immutability?
Gegeben ist ein Programm, das einen Counter mit einer Funktion erhöht:
fn increment(counter: &mut i32) {
*counter += 1;
}
fn main() {
let mut count = 0;
increment(&mut count);
println!("Counter: {}", count);
}
Erkläre die Rolle von mut, &mut und *.
7. Lifetimes:
Aufgabe 10:
Warum kompiliert folgender Code nicht und wie behebt man das Problem?
fn longest(s1: &str, s2: &str) -> &str {
if s1.len() > s2.len() {
s1
} else {
s2
}
}
fn main() {
let string1 = String::from("abc");
let result;
{
let string2 = String::from("xyz");
result = longest(&string1, &string2);
}
println!("{}", result);
}
Erkläre, was Lifetimes sind und warum Rust sie braucht. Behebe den Code mit korrekten Lifetime-Annotationen.