MINT lernen

Abituraufgaben: Lokale und globale Variablen

Zwei Abituraufgaben zu lokalen und globalen Variablen — mit Hinweisen und Erwartungshorizont.

Dein Fortschritt:
0 / 0 Aufgaben
1

Die Stadtbücherei

AFB I–II

Eine Stadtbücherei zählt mit einem kleinen Programm, wie viele Medien eine Familie gerade ausgeliehen hat und wie viel Säumnisgebühr insgesamt angefallen ist. Pro Medium und Tag Verspätung werden 10 Cent fällig.

Java
public class Ausleihe {
    int ausgeliehen = 0;
    int gebuehren = 0;        // in Cent

    void ausleihen(int anzahl) {
        ausgeliehen = ausgeliehen + anzahl;
    }

    int zurueckgeben(int anzahl, int tageZuSpaet) {
        int gebuehr = anzahl * tageZuSpaet * 10;
        ausgeliehen = ausgeliehen - anzahl;
        gebuehren = gebuehren + gebuehr;
        return gebuehr;
    }
}
  1. Nennen Sie alle Variablen der Klasse und geben Sie jeweils an, ob es sich um ein Attribut (global), eine lokale Variable oder einen Parameter handelt.
  2. Ermitteln Sie die Werte der Attribute und die Rückgabewerte nach der Aufruffolge ausleihen(4), zurueckgeben(2, 3), ausleihen(1), zurueckgeben(3, 0).
  3. Beschreiben Sie Gültigkeitsbereich und Lebensdauer der Variable gebuehr. Warum wird die Anweisung System.out.println(gebuehr); in der Operation ausleihen nicht übersetzt?

Hinweise

Hinweis zu Aufgabe a)
Achte darauf, wo jede Variable deklariert ist: in der Klasse, im Kopf oder im Rumpf.
Hinweis zu Aufgabe b)
Lege eine Tabelle an: eine Zeile je Aufruf, eine Spalte je Attribut und eine für die Rückgabe.
Hinweis zu Aufgabe c)
Wann entsteht gebuehr, wann verschwindet sie — und in welchem Block ist sie deklariert?

Erwartungshorizont

Erwartungshorizont zu Aufgabe a)

Attribute (global): ausgeliehen, gebuehren. Parameter: anzahl (in ausleihen), anzahl und tageZuSpaet (in zurueckgeben). Lokale Variable: gebuehr. Die beiden Parameter anzahl sind trotz gleichen Namens verschiedene Variablen.

Erwartungshorizont zu Aufgabe b)
AufrufausgeliehengebuehrenRückgabe
Start00
ausleihen(4)4—
zurueckgeben(2, 3)26060
ausleihen(1)3—
zurueckgeben(3, 0)0600

Am Ende: ausgeliehen = 0, gebuehren = 60. zurueckgeben(2, 3) liefert 2 · 3 · 10 = 60, zurueckgeben(3, 0) liefert 0; ausleihen liefert als void-Operation nichts.

Erwartungshorizont zu Aufgabe c)

gebuehr ist eine lokale Variable von zurueckgeben. Ihr Gültigkeitsbereich reicht von ihrer Deklaration bis zum Ende des Rumpfs dieser Operation. Sie entsteht bei jedem Aufruf von zurueckgeben neu und verschwindet, wenn die Operation endet. In ausleihen ist der Name gebuehr daher unbekannt — der Compiler meldet „cannot find symbol“. Außerdem gäbe es zu dem Zeitpunkt gar keinen Wert: Der letzte Wert existiert nach dem Ende des Aufrufs nicht mehr. Wer die Gebühr später braucht, nutzt den Rückgabewert oder das Attribut gebuehren.

2

Der Kiosk

AFB II–III

Ein Schulkiosk verwaltet seinen Vorrat an belegten Brötchen mit einem Python-Programm. Ein Verkauf gelingt nur, wenn genug Brötchen da sind. Nachbestellte Brötchen sollen den Vorrat erhöhen.

Python
vorrat = 12

def verkaufe(n):
    global vorrat
    if n <= vorrat:
        vorrat = vorrat - n
        return True
    return False

def nachbestellen(menge):
    vorrat = vorrat + menge
  1. Widerlegen Sie die Aussage: „Ob der Aufruf verkaufe(8) gelingt, hängt nur vom Argument 8 ab.“ Betrachten Sie dazu die Aufruffolgen verkaufe(8), verkaufe(5) und verkaufe(5), verkaufe(8), jeweils beginnend mit vorrat = 12.
  2. Zeigen Sie, dass der Aufruf nachbestellen(10) zu einem Laufzeitfehler führt, und korrigieren Sie die Funktion.
  3. Entwerfen Sie eine Fassung von verkaufe und nachbestellen, die ohne globale Variable auskommt, und zeigen Sie deren Aufruf im Hauptprogramm. Gehen Sie auf Vor- und Nachteile Ihres Entwurfs ein.

Hinweise

Hinweis zu Aufgabe a)
Führe für beide Reihenfolgen eine kleine Tracetabelle mit den Spalten vorrat und Rückgabe.
Hinweis zu Aufgabe b)
Nach welcher Regel entscheidet Python, ob vorrat in nachbestellen lokal oder global ist? Was wird rechts vom = gelesen?
Hinweis zu Aufgabe c)
Daten über Parameter hinein, über return heraus. Wo muss dann der Vorrat gespeichert werden?

Erwartungshorizont

Erwartungshorizont zu Aufgabe a)

Reihenfolge 1: verkaufe(8): 8 ≤ 12, vorrat = 4, Rückgabe True. verkaufe(5): 5 ≤ 4 ist falsch, Rückgabe False, vorrat bleibt 4.

Reihenfolge 2: verkaufe(5): vorrat = 7, Rückgabe True. verkaufe(8): 8 ≤ 7 ist falsch, Rückgabe False.

Derselbe Aufruf verkaufe(8) liefert also einmal True und einmal False — die Aussage ist widerlegt. Ursache ist der Seiteneffekt: Das Ergebnis hängt vom globalen Zustand vorrat und damit von der Aufrufreihenfolge ab (Endvorrat 4 bzw. 7).

Erwartungshorizont zu Aufgabe b)

In nachbestellen wird vorrat ein Wert zugewiesen, ohne dass global vorrat steht. Nach der Python-Regel ist vorrat damit in der ganzen Funktion eine lokale Variable. Auf der rechten Seite von vorrat = vorrat + menge wird diese lokale Variable gelesen, bevor sie einen Wert hat. Python bricht mit UnboundLocalError ab; die globale Variable bleibt 12. Korrektur:

Python
def nachbestellen(menge):
    global vorrat
    vorrat = vorrat + menge
Erwartungshorizont zu Aufgabe c)
Python
def verkaufe(vorrat, n):
    if n <= vorrat:
        return vorrat - n
    return vorrat

def nachbestellen(vorrat, menge):
    return vorrat + menge

# Hauptprogramm
bestand = 12
if 8 <= bestand:
    print("Verkauf möglich")
bestand = verkaufe(bestand, 8)       # 4
bestand = nachbestellen(bestand, 10) # 14

Beide Funktionen erhalten den Vorrat als Parameter und geben den neuen Vorrat zurück; der Bestand wird nur im Hauptprogramm gespeichert. Vorteile: keine Seiteneffekte, das Ergebnis hängt nur von den Argumenten ab, die Funktionen sind einzeln testbar und für mehrere Kioske wiederverwendbar. Nachteile: Der Aufrufer muss den Rückgabewert jedes Mal selbst speichern — vergisst er bestand = …, geht die Änderung verloren. Die Information, ob der Verkauf gelungen ist, muss er selbst prüfen (Vergleich vor dem Aufruf oder alter mit neuem Bestand).