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

farbe="schwarz"

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 liefert dabei einen Iterator der mit list(..) in eine Liste umgewandelt werden kann. Z.B. :

In [1]: range(3)          # gibt einen Iterator zurueck
Out[1]: range(0, 3)

In [2]: list( range(3) )  # wandelt den Iterator in eine Liste um
Out[2]: [0, 1, 2]

Diese Funktion kann man ganz allgemein verwendet werden:

In [3]: list( range(1,10,2) )
Out[3]: [1, 3, 5, 7, 9]

In [4]: liste=[1,3,5]

Listen kann man auf 2 Arten durchlaufen:

In [5]: for l in liste :
   ...:     print(l)
   ...:
1
3
5

In [6]: 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:

In [7]: dic = {0:"a", 3:"b", 6:"c" }

In [8]: 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 = int( 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 welche mit int(..) in Zahlen umgewandelt werden. 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 = int( 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

Aufgabe 4.1
Gegeben ist ein String, der beliebig viele Zahlen enthält, die durch Strichpunkte getrennt sind. Aus diesem String sollen die Zahlen extrahiert werden und in Dictionary eingefügt werden, wobei die Zahl als String der Schlüssel und die Zahl als Typ float der Wert sein soll.
Ein guter Programmierstil zeichnet sich dadurch aus, dass möglichst jede Annahme, die über Eingaben getroffen wird, überprüft wird, damit das Programm nicht abstürzt. Aus diesem Grund ist es wichtig zu überprüfen,…
  1. …ob es sich bei der Eingabe tatsächlich um einen String handelt.
  2. …ob die extrahierten Zahlen tatsächlich Zahlen sind.
  3. …ob der neue Schlüssel bereits im Dictionary enthalten ist. Neue Schlüssel sollen erst dann zum Dictionary hinzugefügt werden, wenn sie noch nicht im Dictionary enthalten sind.

Geben Sie mittels print eine Warnung aus, wenn Punkt 1), 2) oder 3) nicht erfüllt werden.

Aufgabe 4.2

Definieren Sie eine beliebige positive, ganze Zahl Testzahl. Überprüfen Sie, ob es sich bei dieser Testzahl um eine Primzahl handelt. Geben Sie True aus, wenn Testzahl 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 Testzahl festgelegt werden und dann für alle Zahlen in diesem Intervall überprüft wird ob sie Teiler von Testzahl 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. weitere Übungsbeispiele

Aufgabe 4.3
Gegeben ist ein Dictionary Woerterbuch, dass als Schlüssel deutsche Wörter und als Werte die entsprechende Übersetzung ins Englische enthält. Z.B. 'gruen': 'green', 'eines': 'a', 'Gras': 'gras', 'ist': 'is', 'eine': 'a', 'das': 'the', 'ein': 'a'.
  1. Erstellen Sie ein 2. Dictionary Woerterbuch_ende, dass die englischen Wöerter als Schlüssel und die deutschen Wörter als Werte enthält.
  2. Ändern Sie Ihre Lösung zu 1), sodass eine Fehlermeldung ausgegeben wird, wenn ein englisches Wort bereits in Woerterbuch_ende enthalten ist.
  3. Erweitern Sie Ihre Lösung zu 2). Wenn zu einem englischen Wort (z.B. a) mehrere deutsche Übersetzungen in Woerterbuch enthalten sind (z.B. ein, eine), wird in Woerterbuch_ende das englische Wort als Schlüssel und eine Liste aller deutschen Übersetzungen als Wert eingefügt.
Aufgabe 4.4

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