add enum / testing example
parent
94df03a758
commit
746558c2ad
|
|
@ -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."),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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!"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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 &eln {
|
||||
println!("{}", aktion(a));
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue