Damit haben wir gleichzeitig ein wichtiges Verständnisproblem geklärt und unsere ersten Strukturen höherer Programmiersprachen – die Zuweisung und die Notation mathematischer Operationen – kennengelernt. Nur um noch einmal sicherzugehen, dass jeder das eben geschriebene auch verstanden hat, noch einmal die beiden obigen Codezeilen als Assemblercode (ja, ein moderner Assembler würde das wegoptimieren, aber darum geht es hier ja nicht):
(2) mov al, x
(3) sub al, 1
(4) mov x, al
An dieser Stelle seien noch schnell zwei wichtige Begriffe eingeführt, die zur Erklärung von Strukturen innerhalb einer Programmiersprache von Bedeutung sind. Der Begriff der Anweisung (engl. statement) wurde bereits erwähnt und bezeichnet eine in sich abgeschlossene Aktion, die unabhängig von den umgebenden Anweisungen ausgeführt werden kann; die Zeilen x ← 4
und x ← x-1
sind Beispiele für derartige Anweisungen. Eine Anweisung setzt sich immer aus einem oder mehreren Ausdrücken (engl. expression) zusammen. Ein Ausdruck stellt dabei eine Operation dar, die einen Wert liefert, etwa das Ergebnis einer Subtraktion; x-1
wäre so ein Ausdruck, aber auch die Konstante 4
, da auch sie einen Wert liefert – eben den Wert 4. Ich werde im Folgenden diese beiden Begriffe konsequent nach dieser Definition verwenden; dem Leser sei also geraten, dem gewählten Begriff Aufmerksamkeit zu schenken.
Und wenn wir schon einmal bei Begriffserklärungen sind, können auch gleich zwei weitere häufig verwendete Wörter erklärt werden: Syntax und Semantik. Die sind allerdings weniger spektakulär: mit Syntax ist die Art und Weise gemeint, wie Code aufgeschrieben wird und ist vergleichbar mit der Orthographie und Grammatik einer natürlichen Sprache. Jede Programmiersprache definiert ihre eigene Syntax, also eine bestimmte Form, wie Konstrukte (also zum Beispiel Anweisungen und Ausdrücke) zu notieren sind. Demgegenüber steht die Semantik, welche den Inhalt des notierten Codes beschreibt, etwa, was der Ausdruck x-1
genau bedeuten soll; die Semantik entspricht also ganz einfach dem Bedeutungsinhalt natürlicher Sprache. Beide Begriffe werden uns ab und zu begegnen, sollten also verinnerlicht werden.
So, das liest sich zwar ganz schön, aber allein mit Zuweisungen und Rechnungen ist natürlich kein Blumentopf zu gewinnen (geschweige denn, ein komplexes Programm zu schreiben). Für erfolgreiches Programmieren braucht man natürlich noch etwas mehr; zum Beispiel Möglichkeiten, den Programmfluss zu steuern. Wir erinnern uns: im Assembler-Code gab es die Anweisung jump
, mit deren Hilfe unbedingt (immer) oder bedingt (nur bei Gültigkeit einer bestimmten Bedingung) an eine bestimmte Stelle im Programmcode gesprungen werden kann. Nun könnte man diese Anweisung auch in einer höheren Programmiersprachen verwenden (und in der Tat lebt sie hier in Form der goto
-Anweisung fort), verzichtet aber in der Regel aus Gründen der Übersichtlichkeit darauf. Stattdessen greift man hier auf sogenannte strukturierte Anweisungen zurück. In der Regel möchte man zwei Dinge mit Sprüngen erreichen (wie es bereits im Assemblercode demonstriert wurde): eine Verzweigung, so dass ein bestimmter Codeteil nur ausgeführt wird, wenn eine bestimmte Bedingung zutrifft; und eine Wiederholung, so dass ein Codeteil mehrere mal ausgeführt wird.
Zuerst zur Verzweigung, der sogenannten if
-Anweisung. Sie besteht aus zwei Bestandteilen: der Bedingung und dem Körper. Die Bedingung ist ein Ausdruck, welcher den Wert true
(wahr) oder false
(falsch) annehmen muss; der Körper ist eine Folge von Anweisungen, die genau dann ausgeführt wird, wenn die Bedingung zu true
evaluiert (das heißt, den entsprechenden Wert annimmt). Diese Struktur heißt Verzweigung, da sie den Programmfluss in zwei mögliche Zweige aufbricht, von denen mal der eine, mal der andere durchlaufen wird. Ein einfaches Beispiel sieht so aus:
(2) x ← 1
(3) y ← 5
Die beiden Zuweisungen in den Zeilen 2 und 3 werden nur dann ausgeführt, wenn die Variable x
einen Wert größer als 1 besitzt. Da es oft auch nötig ist, nicht nur im Fall der zutreffenden Bedingungen, sondern auch im Gegenfall bestimmten Code auszuführen, wird die if
-Anweisung um einen else
-Zweig erweitert. Erweitern wir obiges Beispiel, ergibt sich dadurch zum Beispiel der folgende Code (der hoffentlich selbsterklärend ist):
(2) x ← 1
(3) y ← 5
(4) else:
(5) x ← 0
(6) y ← 2
Neben den Verzweigungen sind Wiederholungen, auch Schleifen genannt, ein wichtiges Element der strukturierten Programmierung. Grundlegend werden zwei Arten von Schleifen unterschieden: die bedingungsgeprüften bzw. while
-Schleifen und die Zähl– bzw. for
-Schleifen. Während
while
-Schleifen so lange laufen, wie eine bestimmte Bedingung erfüllt ist, zählen for
-Schleifen entsprechend ihrem Namen eine bestimmte Anzahl von Durchläufen. Syntaktisch sieht das etwa so aus:
(2) x ← x – 1
(3) y ← y + 1
(4)
(5) for i from x to y:
(6) z ← z + i
Die erste Schleife läuft so lange, wie die Variable x noch größer 1 ist und reduziert in jedem Durchlauf x um 1 und erhöht y gleichzeitig um 1; die zweite Schleife zählt den Wert i einfach von x
nach y
hoch und addiert ihn dabei immer auf die Variable z
. Wer sich an seine Mathematik-Zeit erinnert: letzteres wurde auch gern mit dem Summenzeichen ∑ notiert.
Kommentare (46)