StructorizerHandbuch DE

Instruction (Anweisung)

Klassifikation

Ein Element des Typs „Instruction" (Anweisung) ist das grundlegende algorithmische Element und kann beliebige Befehle oder einfache Anweisungen enthalten. Es gibt fünf grundlegende Arten von Anweisungen (seit Version 3.26-02 werden auch bloße Variablendeklarationen toleriert; Version 3.27 führte zusätzlich die Konzepte der Konstantendefinitionen und Typdefinitionen ein, siehe unten):

  • Eingabe (Input): Eine Eingabeanweisung liest einen vom Benutzer eingegebenen Text und wandelt ihn in den Wert einer bestimmten Variablen um. Eine Eingabeanweisung muss mit dem in den Parser-Einstellungen definierten Eingabe-Schlüsselwort beginnen, auf das ein oder (seit Version 3.29-03) mehrere Variablenbezeichner (z. B. Bezeichner, qualifizierte Namen oder indizierte Array-Variablen) folgen sollen, z. B.:
    • INPUT value
    • INPUT length, width, height
    • INPUT date.day
    • INPUT readings[i]
    Wenn die Eingabeanweisung mehrere Variablen umfasst, sind diese durch Kommas zu trennen. Die Ziele einer Eingabeanweisung werden als neue Variablen registriert, sofern sie noch nicht zuvor eingeführt wurden.
    Um die Eingabe mit einer nicht-generischen Aufforderungsmeldung zu versehen, können Sie ein Zeichenkettenliteral zwischen das Eingabe-Schlüsselwort und die erste Variable setzen (die Aufforderungszeichenkette und die Variable können durch ein Komma getrennt sein oder nicht):
    INPUT "Please enter your name ", name
    Eine Eingabeanweisung ohne Variable ist erlaubt (und wartet lediglich darauf, dass der Benutzer die <Enter>-Taste zur Bestätigung drückt).
  • Ausgabe (Output): Eine Ausgabeanweisung gibt etwas an den Benutzer aus. Eine Ausgabeanweisung muss mit dem in den Parser-Einstellungen konfigurierten Ausgabe-Schlüsselwort beginnen. Nach dem Ausgabe-Schlüsselwort wird ein einzelner Ausdruck oder eine durch Komma getrennte Liste von Ausdrücken erwartet, z. B.:
    OUTPUT "The result is ", value+9, "."
    Die Ausdrücke werden ausgewertet und die Textdarstellungen ihrer Werte in der Reihenfolge ihres Auftretens in eine gemeinsame Ausgabezeile geschrieben. (Abhängig von der Ausgabemodus-Einstellung im Executor-Control erscheint die Zeile entweder im Ausgabe-Konsolenfenster oder in einem separaten Meldungsfeld.) Die nächste Ausgabeanweisung setzt die Ausgabe nicht in derselben Zeile fort, sondern beginnt eine neue Zeile.
    Eine Ausgabeanweisung ohne Ausdruck ist erlaubt und erzeugt eine leere Ausgabezeile (oder ein Meldungsfeld mit dem Hinweis „(empty line)").
  • Zuweisung (Assignment): Hierbei wird eine Variable (die einen Speicherplatz benennt) oder eine Teilstruktur davon mit einem (neuen) Wert belegt, ohne Benutzerinteraktion. Als allgemeine Regel beginnt eine Zuweisung mit einem Variablenbezeichner (üblicherweise ein Bezeichner, kann jedoch auch ein gültiger Zugriffspfad mit Indizes und/oder Komponentennamen sein), gefolgt von einem Zuweisungssymbol, und endet mit einem Ausdruck, dessen berechneter Wert in der Variablen gespeichert werden soll. Akzeptierte Zuweisungssymbole sind „<-" oder „:=". (Das erste davon wird beim Zeichnen des Diagramms als Linkspfeil dargestellt, siehe Abbildungen unten.)
    Beispiele:
    • value <- 17
    • length := 9.3E4
    • date.day := 31
    • line[i] <- "This is just some string."
    Die allererste Zuweisung an eine (neue) Variable wird als Initialisierung bezeichnet. Structorizer registriert eine Variable erst, nachdem sie initialisiert (oder durch eine Eingabeanweisung befüllt) wurde.
    Eine Initialisierung kann mit einer Deklaration (d. h. einer expliziten Typzuordnung) kombiniert werden, wobei Sie zwischen verschiedenen syntaktischen Stilen wählen können (Pascal, Basic, C, Java):
    Deklarationsstile für Arrays seit Version 3.32-04
    Deklarationsstile für Arrays seit Version 3.32-04
    Beachten Sie, dass sich eine solche „typisierte Initialisierung" (die eine wirksame Anweisung darstellt) von einer bloßen Deklaration unterscheidet. Der zugeordnete Typ wird in der Regel nicht erzwungen, d. h. Sie können ihn durch nachfolgende Zuweisungen eines Werts eines abweichenden Typs überschreiben (oder umgehen).
  • Interner Prozeduraufruf (wie z. B. forward(100), um die Schildkröte im Turtleizer-Fenster zu bewegen; weitere Prozeduren siehe Syntax). Um eine nicht eingebaute Prozedur aufzurufen, die auf ein anderes Diagramm verweist, empfiehlt es sich jedoch, ein CALL-Element anstelle eines gewöhnlichen Instruction-Elements zu verwenden.
  • Eine abschließende return-Anweisung für die bedingungslose Rückgabe eines Funktionsergebnisses. „Abschließend" bedeutet, dass sie das allerletzte und bedingungslose Element (Austrittspunkt) des Algorithmus sein muss, d. h. sie muss die gesamte untere Breite des Diagramms einnehmen. Das Diagramm muss vom Unterroutinen-Typ sein (siehe Programm/Unterroutine und Einstellungen). In allen anderen Fällen muss eine return-Anweisung in einem EXIT (Jump)-Element platziert werden (oder ganz vermieden werden).
  • Hilfselemente wie Deklarationen (von Variablen) und Definitionen (von Typen oder Konstanten) sollten vorzugsweise am Anfang eines Diagramms zusammengefasst werden.

Eine Liste der in Anweisungen (und anderen Elementen) verwendbaren eingebauten Operatoren, Funktionen und Prozeduren finden Sie unter Syntax.

IPO-Diagramm in der Normalansicht
IPO-Diagramm in der Normalansicht
IPO-Diagramm im hervorgehobenen Zustand
IPO-Diagramm im hervorgehobenen Zustand

Standarddiagramm versus hervorgehobenes Diagramm

Beispiel

Betrachten wir nun ein etwas aussagekräftigeres Beispiel. Stellen Sie sich vor, Sie möchten Temperaturen in Fahrenheit in Grad Celsius umrechnen. Die Formel lautet:

ϑC = (ϑF - 32) · 5 / 9

Sie benötigen eine Eingabeanweisung, um den Temperaturwert in Fahrenheit abzufragen, bevor Sie die Berechnung anwenden können, und möchten danach eventuell das Ergebnis ausgeben. Der Algorithmus ist also eine Folge von drei Anweisungen, die ein Hauptdiagramm nach dem klassischen IPO-Modell bilden (Eingabe- und Ausgabeanweisungen grün eingefärbt, die Zuweisungsanweisung gelb):

Fahrenheit-Celsius-Umrechnung
Fahrenheit-Celsius-Umrechnung

Die Eingabeanweisung führt implizit die Variable temp_F ein. Die gelbe Zuweisungsanweisung führt die Variable temp_C ein. Die Zuweisung enthält die Formel nahezu wie oben, jedoch mit einigen unscheinbaren, aber wichtigen Unterschieden: Da eine Variable einen benannten Speicherplatz darstellt, der mit einem Wert gefüllt werden muss, benötigen wir einen Zuweisungsoperator (den Linkspfeil oder „:=") anstelle eines Gleichheitszeichens. Die Multiplikation wird durch ein Sternchen ausgedrückt. Bei der Division sollte sichergestellt werden, dass die Zahlen als reelle (Gleitkomma-)Zahlen interpretiert werden, damit das Ergebnis keine ganzzahlige Division ist (die Bruchteile eliminieren würde); daher werden sie besser mit Dezimalpunkten geschrieben.

So erstellen Sie dieses Diagramm:

  1. Beginnen Sie mit einem leeren Diagramm, doppelklicken Sie auf seinen Rahmen, geben Sie den Namen und eine Beschreibung ein und bestätigen Sie mit „OK":
    Ausfüllen des Diagrammrahmens für die Anweisungsdemo
    Ausfüllen des Diagrammrahmens für die Anweisungsdemo
  2. Wählen Sie nun die (leere) Diagrammmitte aus und doppelklicken Sie darauf oder drücken Sie die Taste <F5> oder das Anweisungssymbol (leeres Rechteck) in der Symbolleiste:
    Erstes Anweisungselement einfügen
    Erstes Anweisungselement einfügen
  3. Wenn der Element-Editor öffnet, geben Sie den Text der Eingabeanweisung ein — verwenden Sie das Eingabe-Schlüsselwort aus den Parser-Einstellungen, fügen Sie optional eine Aufforderungszeichenkette hinzu und geben Sie den Variablennamen an:
    Bearbeitung der ersten Anweisung
    Bearbeitung der ersten Anweisung
  4. Das soeben eingefügte Element bleibt ausgewählt, sodass Sie sofort die nächste Anweisung hinzufügen können (erneut mit <F5>, über das Anweisungssymbol, über den Menüpunkt "Diagram › Add › After › Instruction" oder über den entsprechenden Kontextmenüpunkt):
    Zweite Anweisung einfügen
    Zweite Anweisung einfügen
  5. Geben Sie den Zuweisungstext ein (beachten Sie das Zuweisungssymbol zwischen der Zielvariablen auf der linken Seite und dem Ausdruck auf der rechten Seite):
    Text einer Zuweisung eingeben
    Text einer Zuweisung eingeben
  6. Fügen Sie nun die dritte Anweisung hinzu (z. B. über das Kontextmenü):
    Dritte Anweisung einfügen
    Dritte Anweisung einfügen
  7. Wenn Sie möchten, können Sie Anweisungselemente einfärben, um bestimmte Aspekte hervorzuheben (mithilfe der runden Farbpaletten-Schaltflächen):
    Ein Element einfärben
    Ein Element einfärben

Sie können das obige Anweisungsdemo-Diagramm hier herunterladen.

Mehrzeilige Anweisungselemente

Üblicherweise enthält ein Instruction-Element eine einzige Anweisung einer der oben aufgelisteten Arten. Der Einfachheit halber erlaubt Structorizer jedoch, dass ein Instruction-Element mehr als eine Anweisung enthält. Verwenden Sie in diesem Fall eine Zeile pro Anweisung (d. h. eine Anweisung pro Zeile). Beachten Sie jedoch, dass z. B. Haltepunkte nur an ein gesamtes Element, nicht an eine einzelne Zeile geheftet werden können. Es wird nicht empfohlen, Anweisungen verschiedener Art (z. B. Eingabeanweisungen mit Zuweisungen oder Ausgabeanweisungen) innerhalb eines einzigen Instruction-Elements zu kombinieren. Über die Zauberstab-Schaltfläche (Umwandlungsschaltfläche) können Sie eine Folge ausgewählter Instruction-Elemente zu einem einzigen Instruction-Element zusammenführen oder umgekehrt ein mehrzeiliges Instruction-Element in eine Folge separater Instruction-Elemente mit je einer einzigen Anweisungszeile aufteilen.

Diagramm mit verschiedenen Anweisungselementen
Diagramm mit verschiedenen Anweisungselementen

Seit Version 3.27 können Sie sogar lange Anweisungen über mehrere Zeilen verteilen, d. h. den Anweisungstext in aufeinanderfolgenden Zeilen fortsetzen, indem Sie am Ende jeder Zeile (außer der letzten) einen Backslash platzieren — ein Beispiel hierzu finden Sie weiter unten im Abschnitt Typdefinitionen.

Wenn Sie Ihr Diagramm über den Executor testen oder in den Quellcode einer Programmiersprache exportieren möchten, dann:

  • NICHT Anweisungstrennzeichen (wie „;" oder „:") an die Zeilen anhängen;
  • NICHT mehrere Befehle in einer einzigen Zeile auflisten;
  • NICHT leere Zeilen in einem Instruction-Element einfügen (seit Version 3.30-06 überholt).

Variablendeklarationen

Bloße Deklarationen in Pascal- oder BASIC-Syntax werden als Inhalt von Instruction-Elementen toleriert. Um erkannt zu werden, muss eine bloße Variablendeklaration (d. h. ohne Initialisierung) mit einem der Schlüsselwörter var (Pascal) oder dim (BASIC) beginnen. Nach dem Schlüsselwort wird mindestens ein Variablenname (Bezeichner) erwartet (oder eine durch Komma getrennte Bezeichnerliste), dann ein Trennzeichen — entweder : (Pascal) oder as (BASIC) — und ein Typname (Bezeichner) oder eine Array-Spezifikation. Es ist nicht möglich, einen anonymen Record- oder Aufzählungstyp in einer Variablendeklaration zu konstruieren. Array-Spezifikationen müssen auf den Namen eines bekannten Standardtyps (wie integer oder boolean) oder eines zuvor explizit definierten Typs als Elementtyp des Arrays verweisen.

Beispiele für Variablendeklarationen
Beispiele für Variablendeklarationen

Die Typzuordnung durch Variablendeklarationen ist informell und nicht auf eine bestimmte Programmiersprache beschränkt. Bisher schränken die meisten Deklarationen in Structorizer (mit einer wichtigen Ausnahme!) nicht direkt ein, welche Art von Wert Sie einer deklarierten Variablen zuweisen können — Sie können den deklarierten Typ jederzeit durch eine Zuweisung eines Werts eines abweichenden Typs überschreiben. Die Deklaration kann jedoch den Code-Export beeinflussen und unter bestimmten Umständen in eine korrekte Deklaration in der Zielsprache umgewandelt werden.

Die erwähnte Ausnahme von der Typtoleranz sind die Record-Typen (auch Struct-Typen, ebenfalls mit Version 3.27 eingeführt). Da auf Komponenten von Variablen dieser Typen über Komponentennamen zugegriffen wird, die an einen Record-Variablennamen angehängt werden (dem Variablenbezeichner folgt ein Punkt und der Komponentenname), ist die Kenntnis der benutzerdefinierten Struktur einer Variablen für das Parsen von Ausdrücken unerlässlich.

Beachten Sie, dass durch bloße Deklarationen eingeführte Variablennamen nicht hervorgehoben werden, solange die Variablen nicht irgendwo initialisiert werden.

Konstantendefinitionen

Instruction-Elemente können auch Konstantendefinitionen enthalten. Syntaktisch sehen sie genauso aus wie Variablenzuweisungen, jedoch mit dem vorangestellten Schlüsselwort const. Semantisch werden Konstanten von Structorizer tatsächlich wie unveränderliche Variablen behandelt. Das bedeutet, dass sie nur einmal gesetzt werden können. Der Wert kann durch einen Ausdruck berechnet werden. Der Analyser kann prüfen, ob alle beteiligten Operanden Literale, definierte Konstanten oder selbst konstante Ausdrücke sind. Weitere Versuche, einer Konstante einen anderen Wert zuzuweisen oder den definierten Wert zu ändern, werden vom Executor verhindert.

Beispiele für Konstantendefinitionen und Variablendeklarationen
Beispiele für Konstantendefinitionen und Variablendeklarationen

Die formalen Parameter von Routinen können ebenfalls durch Voranstellen des Schlüsselworts const als konstant deklariert werden. In diesem Fall darf der beim Aufruf der Routine übergebene Wert innerhalb der Funktion nicht verändert werden (Nur-Lese-Semantik). Bei übergebenen Arrays oder Records erhalten Sie lediglich eine unveränderliche Kopie.

Die linke Seite einer Konstantendefinition (d. h. links vom Zuweisungssymbol) kann auch eine Typspezifikation enthalten, die einer initialisierenden Variablendeklaration ähnelt, mit dem Unterschied, dass das Schlüsselwort const das Schlüsselwort var oder dim ersetzt. Typspezifikationen sind hier redundant, da der Typ aus dem konstanten Ausdruck abgeleitet werden kann, können aber beim Code-Export hilfreich sein.

Typdefinitionen

Instruction-Elemente können auch Typdefinitionen enthalten. Wie im Absatz über Variablendeklarationen beschrieben, wurden sie mit der Einführung von Record-/Struct-Typen notwendig und danach für andere Typen verallgemeinert.

Eine Typdefinition beginnt mit dem reservierten Wort type, gefolgt vom Namen des neuen zu definierenden Typs (ein Bezeichner), einem Gleichheitszeichen und — auf der rechten Seite davon — der Typspezifikation.

Für einen zusammengesetzten Typ muss als nächstes das reservierte Wort record oder — synonymisch — struct und eine öffnende geschweifte Klammer folgen. Nach der Klammer wird eine Liste von Komponentendeklarationen erwartet, die ähnlich wie Parameterdeklarationen einer Unterroutine aussehen; Pascal-Stil (name: Typ) sowie BASIC-Stil (name as Typ) und C-Stil (Typ name) werden akzeptiert, müssen jedoch durch Semikolons (!) getrennt werden. Nur im Pascal-Stil sind Gruppendeklarationen erlaubt: Mehrere Komponentennamen mit einem gemeinsamen Typ können durch Kommas getrennt vor dem Doppelpunkt aufgelistet werden. Schließlich ist die Deklarationsliste mit einer schließenden geschweiften Klammer abzuschließen (diese Syntax ist eine Mischung aus Pascal und C):

Zwei verschachtelte Record-Typen definiert
Zwei verschachtelte Record-Typen definiert

Wenn Sie eine Typdefinition über mehrere Zeilen verteilen möchten, muss jede Zeile außer der letzten mit einem Backslash enden.

Für einen Aufzählungstyp (Versionen ≥ 3.30-03) wird das reservierte Wort enum erwartet (anstelle von struct oder record), ebenfalls gefolgt von einer öffnenden geschweiften Klammer. Zwischen der öffnenden und der schließenden geschweiften Klammer wird eine durch Komma getrennte Folge von Aufzählungsnamen (eindeutige Bezeichner) erwartet. Jedem Aufzählungsnamen wird eine ganzzahlige Konstante zugewiesen, deren numerischer Wert von Structorizer inkrementell ab 0 vergeben wird. Sie können eine andere Kodierung angeben, indem Sie einem Aufzählungsnamen über ein Gleichheitszeichen einen expliziten nicht-negativen ganzzahligen Wert zuordnen.

Zwei Typdefinitionen ohne und mit Code-Einstellung
Zwei Typdefinitionen ohne und mit Code-Einstellung

Für einen Array-Typ (als Typdefinition seit Version 3.32-12 unterstützt) gibt es zwei Möglichkeiten, ihn auf der rechten Seite des Gleichheitszeichens in einer Typdefinition anzugeben:

  • Pascal-Stil: beginnt mit dem reservierten Wort array, gefolgt von einem oder mehreren Indexbereichen in einem gemeinsamen eckigen Klammerpaar, gefolgt vom Schlüsselwort of und dem Namen des Elementtyps (oder rekursiv einer weiteren Array-Spezifikation);
  • C-Stil: der Name des Elementtyps (ein Bezeichner), gefolgt von einem oder mehreren Klammernpaaren, die jeweils eine oder mehrere nicht-negative ganze Zahlen enthalten. Die Zahlen geben an, wie viele Zeilen (Spalten usw.) das Array haben soll.

Ein dreidimensionaler Array-Typ aus Gleitkommazahlen mit doppelter Genauigkeit könnte daher auf folgende äquivalente Arten angegeben werden:

  • array [0..9, 0..14, 0..3] of double
  • array [0..9, 0..14] of array [0..3] of double
  • array [0..9] of array [0..14] of array [0..3] of double
  • double [10, 15, 4]
  • double [10] [15, 4]

Hinweis: Es ist nicht erlaubt, einen Array-Typ über eine anonyme zusammengesetzte oder Aufzählungstyp-Konstruktion zu definieren. Wenn Sie einen Array-Typ mit z. B. einem Record-Typ als Elementtyp definieren möchten, müssen Sie zunächst den Record-Typ definieren (und ihm damit einen Namen geben) und ihn dann über seinen Namen in der Array-Typdefinition referenzieren.

Schließlich kann eine Typdefinition auch einfach einen Alias für einen anderen Typ benennen.

Diagramm mit mehreren Typdefinitionen, darunter Arrays und Alias-Typen
Diagramm mit mehreren Typdefinitionen, darunter Arrays und Alias-Typen

Definierte Typen können auch als Parametertypen für Unterroutinen verwendet werden. Beachten Sie jedoch, dass in diesem Fall beide Diagramme (das aufrufende und das aufgerufene) den Typ kennen müssen, da sonst die Argumentübergabe nicht funktionieren würde. Um die Typdefinition zu teilen, müssen Sie sie in ein zusätzliches Diagramm des Typs Includable legen und den Namen dieses Includable-Diagramms in die Include-Liste beider kommunizierenden Diagramme aufnehmen (Zugriff auf die Include-Liste eines Diagramms über die Schaltfläche „Diagrams to be included" im Programm/Unterroutinen-Editor).