4. Kontrollstrukturen

Kontrollstrukturen helfen den Ablauf eines Programms zu steuern. Man unterscheidet:

  • Fallunterscheidungen (if, else) und
  • Schleifen (for, while)

4.1. Fallunterscheidungen

4.1.1. If, elif, else

Die einfachste Möglichkeit der Fallunterscheidung ist die if - Anweisung. Diese sieht folgendermaßen aus:

if Bedingung :    # Anweisungskopf
   Anweisung      #   |
   ...            #   | Anweisungskörper
   Anweisung      #   |

Diese besteht aus einem

  • Anweisungskopf, der eine Bedingung enthält und einem
  • Anweisungskörper (Codeblock) welcher je nach Ergebnis der Bedingung ausgeführt wird.

Anders gesagt WENN Bedingung erfüllt, dann mach, was im Anweisungskörper steht. Z.B:

if x < 1 :
    print "x kleiner 1"

Bemerkung

  • Der Anweisungskopf endet mit einem :.
  • Der Anweisungskörper ist eingerückt!
  • Die gleiche Einrückung, wie das if bedeutet die Anweisung ist außerhalb des Anweisungskörpers!

Die Abbildung if-Anweisung grafisch zeigt diese als Flußdiagramm.

_images/ifAnweisung.jpg

if-Anweisung grafisch

Möchte man eine weitere Bedingung prüfen (wenn die erste False war), verwendet man eine elif - Anweisung.

if Bedingung1 :     # Pruefe Bed 1
   Anweisung        #   |
   ...              #   | wenn Bed 1 True
   Anweisung        #   |

elif Bedingung2 :   # Pruefe Bed 2
   Anweisung        #   |
   ...              #   | wenn Bed 2 True
   Anweisung        #   |

Beispiel:

if x < 1:
    print "x kleiner 1"
elif x == 1:
    print "x gleich 1"

Soll eine Anweisung ausgeführt werden wenn keine der beiden Bedingungen greift, verwendet man eine else - Anweisung.

if Bedingung1 :     # Pruefe Bed 1
   Anweisung        #   |
   ...              #   | wenn Bed 1 True
   Anweisung        #   |

elif Bedingung2 :   # Pruefe Bed 2
   Anweisung        #   |
   ...              #   | wenn Bed 2 True
   Anweisung        #   |

else :              # Sonst
   Anweisung        #   |
   ...              #   | wenn Bed 1 und 2 False
   Anweisung        #   |

Beispiel:

if x < 1:
    print "x kleiner 1"
elif x == 1:
    print "x gleich 1"
else:
    print "x ist groesser 1"

Mit dieser Art der Fallunterscheidung lassen sich auch switch case Kontrollstrukturen (wie in Java oder C++) realisieren. Beispiel (kontroll_switch.py):

Die Abbildung if-elif-else-Anweisung grafisch zeigt diese als Flußdiagramm.

_images/ifElifElseAnweisung.jpg

if-elif-else–Anweisung grafisch

if farbe == "rot":
    print "Farbe rot"
elif farbe == "blau":
    print "Farbe blau"
elif farbe == "gelb":
    print "Farbe gelb"
else : 
    print "Farbe ", farbe, " nicht bekannt!" 

Die häufigste Verwendung sind if-else Konstrukte (WENN - dann - SONST):

if Bedingung :      # Pruefe Bed
   Anweisung        #   |
   ...              #   | wenn True
   Anweisung        #   |

else :              # Sonst
   Anweisung        #   |
   ...              #   | wenn Bed False
   Anweisung        #   |

Hinweis

Wenn möglich if Schleifen immer mit else versehen! Somit erkennt man Programmierfehler leichter.

4.2. Schleifen

4.2.1. For - Schleifen

Eine for-Schleife ist eine Zählschleife. Die Anzahl der Schleifendurchläufe kann mit dem Schleifenzähler angegeben werden:

for Variable in Objekt :      # nimm aus Obj eine Var
   Anweisung                  #   |
   ...                        #   | mach was damit
   Anweisung                  #   |

Beispiel (kontroll_for.py):

for i in range(3) :
    print i

Ausgabe:

0
1
2

Die range(..) Funktion erzeugt dabei eine Liste ([0, 1, 2]) mit 3 Zahlen. Diese kann man ganz allgemein verwendet werden:

>>> range(1,10,2)   # start (inklusive), stop (exklusive), step
[1, 3, 5, 7, 9]

Listen kann man auf 2 Arten durchlaufen:

>>> liste = [1,3,5]
>>> for l in liste :
...     print l
1
3
5

>>> for i in range(len(liste)) :
...     print i, liste[i]
0 1
1 3
2 5

je nach dem ob man den Index i benötigt oder nicht. Dictionaries durchläuft man z.B. mit:

>>> dic = {0:"a", 3:"b", 6:"c" }
>>> for key in dic:
...     print key, dic[key]
...
0 a
3 b
6 c

Die Abbildung for Schleife grafisch zeigt diese als Flußdiagramm.

_images/forSchleife.jpg

for Schleife grafisch

4.2.2. While - Schleifen

Diese führen Codeblock so lange aus, wie eine bestimmte Bedingung erfüllt ist.

while Bedingung :             # solange Bed True
   Anweisung                  #   |
   ...                        #   | mach was damit
   Anweisung                  #   |

Das Flussdiagramm sieht wie bei Abbildung for Schleife grafisch aus. Beispiel (kontroll_while.py):

geheimnis = 1337 
rate  = 0 
while rate != geheimnis: 
    rate = input("Raten Sie: ") 
print ("Sie haben es geschafft!")

Ausgabe:

Raten Sie: 1234
Raten Sie: 1543
Raten Sie: 1337
Sie haben es geschafft!

Im Vergleich zur for Schleife kennt man bei der while Schleife die Anzahl der Schleifendurchläufe nicht!

Bemerkung

Die input Anweisung liest dabei zeichen von der Python Shell ein. Mit ENTER bestätigt man diese Eingabe.

Warnung

While Schleifen sind gefährlich! Schlechte Programmierung kann zu Endlosschleifen führen. Dann hilft manchmal nur mehr ein Programmabbruch ...

4.2.3. Vorzeitiger Abbruch eines Schleifendurchlaufs

Es gibt Möglichkeiten den Ablauf einer Schleife zu beeinflussen.

  • break Anweisung: beendet den gesamten Schleifendurchlauf, verläßt die Schleife.
  • continue Anweisung: beendet den aktuellen Schleifendurchlauf, startet den nächsten Durchlauf.

Schematisch sieht dies so aus:

while Bedingung :             #  <-
   ...                        #    |
   if Bedingung1:             #    | springt nach oben
      continue                #  --
      ...
   if Bedingung2:             #
      break                   #  --
   ...                        #    | springt nach unten
...                           #  <-

Beispiel (kontroll_while_break_continue.py):

while True: 
    zahl = input("Positive Zahl eingeben : ") 

    if zahl < 0: 
        print "Negative Zahlen nicht erlaubt!" 
        continue 

    if zahl == 0: 
        print "Skript wird beendet!" 
        break 
    
    print "Zahl =", zahl

Ausgabe:

Positive Zahl eingeben : 22
Zahl = 22
Positive Zahl eingeben : -3
Negative Zahlen nicht erlaubt!
Positive Zahl eingeben : 6
Zahl = 6
Positive Zahl eingeben : 0
Skript wird beendet!

4.3. Die pass Anweisung

Während der Entwicklung eines Programms kommt es vor, dass

  • eine Kontrollstruktur vorerst nur teilweise implementiert wird.
  • Der Anweisungskopf wird erstellt, es fehlt jedoch der Anweisungskörper.
  • Ein fehlender Anweisungskörper wäre aber ein Syntaxfehler.
  • Abhilfe schafft dabei die pass Anweisung.

Beispiel:

if x == 1:
   pass                       # wird später implementiert
elif x == 2:
   print "x hat den Wert 2"
else :
   print "Weder 1 noch 2."

4.4. Übungsbeispiele 4

Aufgabe 4.1

In der Programmierung ist es guter Stil möglichst jede Annahme, die über Eingaben getroffen wird zu überprüfen, damit Ihr Programm nicht abstürzt. Verändern Sie dazu Ihr Beispiel aus Aufgabe 3.3 durch if-Abfragen an geeigneten Stellen:

  1. Zu Beginn nehmen Sie an, dass ein String definiert ist. Überprüfen Sie, dass es sich bei der Eingabe tatsächlich um einen String handelt.
  2. Sie nehmen an, dass sich die extrahierten Zahlen zu float-Zahlen konvertieren lassen. Überprüfen Sie vor der Konvertierung, dass es sich um Zahlen handelt.
  3. Fügen Sie einen Schlüssel erst dann zum Dictionary hinzu, wenn der Schlüssel noch nicht im Dictionary enthalten ist. Geben Sie mittels print eine Warnung aus, wenn der Schlüssel schon existiert.

Hinweis

Überprüfen Sie dass Ihre Abfragen korrekt funktionieren, indem Sie falsche Eingaben definieren, z.B. Zahlen statt des Strings.

Aufgabe 4.2

Definieren Sie eine beliebige ganze Zahl Zahl. Überprüfen Sie, ob es sich bei dieser Zahl um eine Primzahl handelt. Geben Sie True aus, wenn Zahl eine Primzahl ist, bzw. False, wenn nicht.

Hinweis

Dazu kann z.B. ein ganz primitiver Algorithmus verwendet werden, bei dem zunächst eine untere und obere Schranke für die möglichen Teiler der Zahl festgelegt werden und dann für alle Zahlen in diesem Intervall überprüft wird ob sie Teiler von Zahl sind.

Testen Sie Ihre Funktion an einigen Zahlen, z.B.

  • keine Primzahlen: 323, 1, ...
  • Primzahlen: 2, 43, 97, ...

Hinweis

1 ist keine Primzahl.

Beachten Sie bei Verwendung von range, dass die obere Grenze nicht angenommen wird!

4.5. Hausaufgaben

Hausaufgabe 3.1 (1 Punkt)

Gegeben ist ein Dictionary Messung mit folgendem Inhalt: '10' : 450.66, '23' : 340.29, '35' : 270.63, '37' : 104.67. Die Schlüssel sind strings und geben die Identifikationsnummer einer Messung an. Der entsprechende Wert stellt den Messwert dar. Unterschreitet eine beliebige Messung einen Wert von 300, wird dieser als Ausreißer gezählt. Definieren Sie hierfür eine Variable Grenze mit dem Wert 300. Erstellen Sie zwei Listen Ausreisser und OK. Die Listen sollen jeweils die Identifikationsnummer der Messung enthalten. Achten Sie darauf, dass in der Liste Ausreisser wirklich NUR die Ausreißer enthalten sind, während in der Liste OK nur Messungen enthalten sind, die nicht als Ausreißer angesehen werden. Geben Sie abschließend beide Listen in Ihrer Konsole aus.

Testen Sie Ihren Code an Dictionaries mit unterschiedlichem Inhalt und unterschliedlicher Länge. Geben Sie in Ihrem Code an, welche Dictionaries Sie getestet haben.

Hausaufgabe 3.2 (1 Punkt)

Ziel dieser Aufgabe ist es, aus einer Liste von Anmeldungen für einen Kurs jene Teilnehmer zu ermitteln, die auch bezahlt haben. Nachname und Alter dieser Teilnehmer sollen in einem Dictionary gespeichert werden.

Gegeben ist hierfür eine Liste Anmeldungen, die als Einträge jeweils eine Liste pro Person mit den Daten Vorname, Nachname und Alter enthält:

Anmeldungen = [["Michael","Jahn",23],
               ["Natalia","Pauli",20],
               ["Manuel","Berger",20],
               ["Heinrich","Meier",39]]

Die Liste Bezahlt enthält die Nachnamen aller Teilnehmer, die bezahlt haben:

Bezahlt = ["Pauli", "Jahn", "Meier"]
Gehen Sie nun wie folgt vor:
  1. Legen Sie ein leeres Dictionary Kursteilnehmer an.
  2. Lesen Sie mit Hilfe einer Schleife den Nachnamen und das Alter jeder Person aus Anmeldungen aus.
  3. Überprüfen Sie, ob die Person bezahlt hat, das heißt, ob sich der Name in der Liste Bezahlt befindet.
  4. Wenn die Person bezahlt hat, Tragen Sie die Person in das Dictionary Kursteilnehmer ein. Verwenden Sie den Nachnamen als Schlüssel und das Alter als Wert.
  5. Geben Sie das Dictionary Kursteilnehmer in Ihrer Konsole aus.

4.6. weitere Beispiele

Aufgabe 4.3

Definieren Sie eine Zeichenkette beliebiger Länge. Bestimmen Sie die Anzahl der Vokale (a,e,i,o,u) in diesem String und geben sie diese aus. Testen Sie Ihr Skript an beliebigen Zeichenketten.

Hinweis

Verwenden Sie for..in.. und if..in...

Aufgabe 4.4

Definieren Sie ein Dictionary, das als Schlüssel einige Namen und als Werte das dazugehörige Alter enthält, z.B. "Anton" : 20, "Julia" : 14, "Bernhard" : 19, "Sandra" : 22.

Suchen Sie aus diesem Dictionary die Namen aller Personen, die älter als 20 sind und schreiben Sie diese Namen in eine neu erstellte Liste.

Testen Sie Ihren Code an Dictionaries mit verschiedenen Längen!