CS_LEVEL_26_SOLUTION - OnlyCook/abitur-elite-code GitHub Wiki
Level 26 – Musterlösung: Das Abrechnungssystem (Teil 3)
Lösung
public int VerarbeiteGepaeckString(string daten)
{
string[] teile = daten.Split(';');
if (teile.Length == 3)
{
if (teile[0] == "BGG")
{
int passID = Int32.Parse(teile[1]);
double gewicht = Double.Parse(teile[2]);
Passagier p = SuchePassagier(passID);
if (p != null)
{
int tageBisAbflug = (p.GetFlug().GetStartDatum() - DateTime.Now).Days;
if (tageBisAbflug > 0)
{
if (gewicht > 20.0)
{
double zuschlag = (gewicht - 20.0) * 15;
return (int)zuschlag;
}
return 0;
}
return -3;
}
return -2;
}
return -1;
}
return -1;
}
public Passagier SuchePassagier(int id)
{
foreach (Passagier p in passagiere)
{
if (p.GetPassagierID() == id)
{
return p;
}
}
return null;
}
Erklärung
Abschluss von Sektion 6
Das letzte Level – und kein neues Konzept, das du noch nicht gesehen hättest. Die Aufgabe ist, ein Nassi-Shneiderman-Diagramm (Struktogramm) sauber in Code zu übersetzen und dabei alle Sonderfälle korrekt abzubilden. Genau das ist Abitur.
Vom Nassi-Shneiderman-Diagramm zum Code
Das Diagramm beschreibt den Algorithmus als verschachtelte Bedingungsblöcke. Das Struktogramm hat ein ergebnis-Muster: erst wird ergebnis gesetzt, am Ende zurückgegeben. Das funktioniert, ist aber unnötig umständlich.
Die sauberere Variante nutzt frühe return-Anweisungen: sobald klar ist, was zurückgegeben wird, wird sofort zurückgegeben. Das spart Einrückungstiefe und ist leichter zu lesen. Beide Varianten sind korrekt – im Abitur ist das Structorizer-Muster mit ergebnis aber ebenfalls akzeptiert.
Die verschachtelte Struktur der if-Blöcke spiegelt das Diagramm direkt wider:
Länge == 3?
└─ erstes Element == "BGG"?
└─ Passagier gefunden?
└─ Abflug in der Zukunft?
└─ Gewicht > 20?
→ Zuschlag berechnen
→ 0
→ -3
→ -2
→ -1
→ -1
Jede Ebene im Diagramm entspricht einem if-Block im Code. Wenn eine Bedingung nicht erfüllt ist, wird sofort der zugehörige Fehlerwert zurückgegeben – es wird nicht tiefer gegangen.
Datumsberechnung
int tageBisAbflug = (p.GetFlug().GetStartDatum() - DateTime.Now).Days;
if (tageBisAbflug > 0)
p.GetFlug() liefert das Flug-Objekt des Passagiers – dafür braucht Passagier einen GetFlug()-Getter, der analog zu GetPassagierID() implementiert wird. GetStartDatum() gibt dann das DateTime-Feld zurück.
Zwei DateTime-Werte subtrahiert ergeben ein TimeSpan-Objekt. Dessen .Days-Eigenschaft gibt die ganzzahlige Anzahl der Tage zurück. Liegt das Startdatum in der Vergangenheit, ist das Ergebnis negativ – die Bedingung > 0 schließt das sauber aus.
Zuschlagsberechnung und Cast
double zuschlag = (gewicht - 20.0) * 15;
return (int)zuschlag;
Der Zuschlag wird als double berechnet, aber als int zurückgegeben – der Cast schneidet die Nachkommastellen ab (kein Runden). Bei 25.5 kg ergibt das: (25.5 - 20.0) * 15 = 82.5 → 82. Das ist aus dem Diagramm zu lesen, da nicht explizit nach Rundungen gefragt wird.
SuchePassagier – lineare Suche
public Passagier SuchePassagier(int id)
{
foreach (Passagier p in passagiere)
{
if (p.GetPassagierID() == id)
{
return p;
}
}
return null;
}
Die Hilfsmethode durchsucht die interne Passagierliste linear. Wird ein Passagier mit passender ID gefunden, wird er sofort zurückgegeben. Wenn die Schleife ohne Treffer endet, kommt null zurück – und im aufrufenden Code wird genau darauf geprüft (if (p != null)).