add enum / testing example

main
dstuck 2026-06-14 14:32:45 +02:00
parent 94df03a758
commit 746558c2ad
9 changed files with 206 additions and 0 deletions

View File

@ -0,0 +1,25 @@
// Jede Variante kann unterschiedliche Daten tragen.
enum Tier {
Hund(String), // Tupel-Variante: Name
Fisch { art: String, liter: u32 }, // Struct-Variante: benannte Felder
Stein, // Keine Daten
}
fn main() {
let haustiere = vec![
Tier::Hund("Bello".into()),
Tier::Fisch {
art: "Goldfisch".into(),
liter: 60,
},
Tier::Stein,
];
for tier in &haustiere {
match tier {
Tier::Hund(name) => println!("{name} will Gassi gehen"),
Tier::Fisch { art, liter } => println!("{art} braucht {liter}L Aquarium"),
Tier::Stein => println!("...braucht nichts."),
}
}
}

View File

@ -0,0 +1,21 @@
// Option<T> ersetzt null/nil. Der Compiler erzwingt, dass ihr den "nichts da"-Fall behandelt.
fn teile(a: f64, b: f64) -> Option<f64> {
if b == 0.0 {
None // Kein Ergebnis möglich
} else {
Some(a / b) // Ergebnis einpacken
}
}
fn main() {
let versuche = vec![(10.0, 3.0), (5.0, 0.0), (42.0, 7.0)];
for (a, b) in versuche {
// Ohne diesen match kompiliert der Code nicht ihr MÜSST den None-Fall behandeln.
match teile(a, b) {
Some(ergebnis) => println!("{a} / {b} = {ergebnis:.2}"),
None => println!("{a} / {b} = nicht möglich!"),
}
}
}

View File

@ -0,0 +1,27 @@
// Result<T, E> modelliert Erfolg ODER Fehler. Jeder Fehlertyp ist eine eigene Enum Variante.
#[derive(Debug)] //generiert automatisch eine Debug-Ausgabe
enum FehlerArt {
ZuKurz,
KeineZahl,
}
// Rückgabe ist entweder Ok(eine_zahl) oder Err(ein_fehler)
fn parse_alter(input: &str) -> Result<u32, FehlerArt> {
if input.len() < 1 {
return Err(FehlerArt::ZuKurz);
}
input.parse::<u32>().map_err(|_| FehlerArt::KeineZahl)
}
fn main() {
let eingaben = vec!["25", "", "abc", "42"];
for e in eingaben {
match parse_alter(e) {
Ok(alter) => println!("\"{e}\" → Alter: {alter}"),
Err(FehlerArt::ZuKurz) => println!("\"{e}\" → Fehler: leere Eingabe"),
Err(FehlerArt::KeineZahl) => println!("\"{e}\" → Fehler: keine gültige Zahl"),
}
}
}

View File

@ -0,0 +1,16 @@
// Match Guards: ein `if` nach dem Pattern fügt eine zusätzliche Bedingung hinzu.
fn bewerte_note(punkte: u32) {
match punkte {
p if p >= 90 => println!("{p} Punkte → Sehr gut"),
p if p >= 75 => println!("{p} Punkte → Gut"),
p if p >= 50 => println!("{p} Punkte → Bestanden"),
p => println!("{p} Punkte → Durchgefallen"),
}
}
fn main() {
for p in [95, 80, 55, 30] {
bewerte_note(p);
}
}

View File

@ -0,0 +1,55 @@
// Patterns können beliebig tief verschachtelt werden:
// Structs in Enums in Options alles in einem match.
enum Inhalt {
Text(String),
Zahl(i32),
}
struct Paket {
absender: String,
inhalt: Option<Inhalt>,
}
fn oeffne(p: &Paket) {
match p {
// Option UND Enum gleichzeitig destrukturieren
Paket {
absender,
inhalt: Some(Inhalt::Text(t)),
} => {
println!("Von {absender}: Text \"{t}\"");
}
Paket {
absender,
inhalt: Some(Inhalt::Zahl(n)),
} => {
println!("Von {absender}: Zahl {n}");
}
// .. deckt restliche Felder ab (hier: absender)
Paket { inhalt: None, .. } => {
println!("Leeres Paket.");
}
}
}
fn main() {
let pakete = vec![
Paket {
absender: "Alice".into(),
inhalt: Some(Inhalt::Text("Hallo".into())),
},
Paket {
absender: "Bob".into(),
inhalt: Some(Inhalt::Zahl(99)),
},
Paket {
absender: "Eve".into(),
inhalt: None,
},
];
for p in &pakete {
oeffne(p);
}
}

View File

@ -0,0 +1,24 @@
// Exhaustiveness: der Compiler prüft, ob ALLE Varianten abgedeckt sind. Vergisst man eine → Compilerfehler.
enum Ampel {
Rot,
Gruen,
// Gelb, // ← einkommentieren und neu kompilieren!
}
fn aktion(a: &Ampel) -> &str {
match a {
Ampel::Rot => "Stehen bleiben",
Ampel::Gruen => "Gehen",
// Ohne Arm für Gelb → Compilerfehler:
// "non-exhaustive patterns: `Gelb` not covered"
}
}
fn main() {
let ampeln = [Ampel::Rot, Ampel::Gruen];
for a in &ampeln {
println!("{}", aktion(a));
}
}

View File

View File

@ -0,0 +1,38 @@
// Tests werden mit "cargo test" ausgeführt
fn is_even(n: i32) -> bool {
n % 2 == 0
}
fn double(n: i32) -> i32 {
n * 2
}
fn add_one(n: i32) -> i32 {
n + 1
}
fn main() {
println!("{} ist gerade: {}", 4, is_even(4));
println!("doppelt von 5: {}", double(5));
}
// Tests liegen generell im selben file wie die Function selbst
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn even() {
assert!(is_even(4)); // bool
}
#[test]
fn double_of_5() {
assert_eq!(double(5), 10); // Vergleich auf Gleichheit
}
#[test]
fn add_one_changes_value() {
assert_ne!(add_one(5), 5); // Vergleich auf Ungleichheit
}
}

View File