Implemented the homework exercises

main
Oliver Stolle3024383 2026-06-10 20:04:42 +00:00
parent 75a0e0e42e
commit 51f91b8c2c
1 changed files with 260 additions and 3 deletions

View File

@ -2,8 +2,265 @@
## 1. Ownership & Borrowing:
## 2. Pattern Matching
### Aufgabe 1:
Erkläre, warum folgender Rust-Code nicht kompiliert:
```rust
fn main() {
let s1 = String::from("Hallo");
let s2 = s1;
println!("{}", s1);
}
```
Ändere den Code so, dass ```s1``` und ```s2``` augegeben werden können.
<br> <br>
### Aufgabe 2:
Warum verbietet Rust folgenden Code?
```rust
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:
```rust
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:
```rust
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").
<br>
### 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`.
```rust
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?
```rust
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.
<br>
### Aufgabe 7:
Was ist der Unterschied zwischen folgenden zwei Funktionen? Welche ist besser und warum?
```rust
// 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:
```rust
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:
```rust
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:
```rust
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?
```rust
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.
## 9. Error Handling und Panic:
### Aufgabe 11:
Was ist der Unterschied zwischen `panic!` und `Result`? Wann sollte man welches verwenden?
Schreibe eine Funktion `divide`, die zwei Zahlen dividiert:
- Bei erfolgreicher Division: Rückgabe des Ergebnisses
- Bei Division durch Null: Rückgabe eines fehlers als `Result<f64, String>`
```rust
fn divide(a: f64, b: f64) -> Result<f64, String> {
// TODO
}
fn main() {
match divide(10.0, 2.0) {
Ok(result) => println!("Ergebnis: {}", result),
Err(e) => println!("Fehler: {}", e),
}
}
```
Erkläre, warum `Result` sicherer ist als ein `panic!` in einer Library-Funktion.
## 3. Enums
## 4. Lifetimes