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)).


🎉 Glückwunsch – du hast alle 26 Level abgeschlossen! 🎉