Das R-BASIC Handbuch im HTML-Format
Startseite  > R-BASIC  > Das R-BASIC Handbuch im HTML-Format

Das R-BASIC Programmierhandbuch

Einfach unter PC/GEOS programmieren

Autor: Rainer Bettsteller
HTML-Version: Mütze - Hinweise & Fehler an

Ein Anfänger-Tutorial

Dieses Tutorial beschreibt an einem einfachen Beispiel, wie man ein R-BASIC Programm erstellt. Dabei werden viele Fakten und Zusammenhänge einfach benutzt, ohne sie ausführlich zu erklären. Stattdessen gibt es jeweils Verweise auf die Kapitel im Handbuch, wo Sie weiterführende Erklärungen finden. Einige Begriffe sind fett markiert. Diese Begriffe kommen im Handbuch immer wieder vor. Eine exakte Erklärung dieser Begriffe finden Sie im nächsten Kapitel.

Die Schrittfolge, die hier dargestellt wird, können Sie prinzipiell auf jedes Programm anwenden.

^

1. Der Plan ...

Als Einstieg wollen wir uns ansehen, wie man das folgende Programm erstellt. Der Nutzer soll eine Zahl eingeben und das Programm soll prüfen, ob die Zahl gerade ist oder nicht.

^

2. Die UI (das User-Interface)

Das Erstellen eines Programms beginnt in den allermeisten Fällen mit der Programmierung der Benutzeroberfläche, der UI. Das heißt, Sie legen fest welche Objekte es gibt und wie sie angeordnet sind.

Jedes Objekt hat einen Typ, der Programmierer sagt, es gehört einer Klasse an. Die Klasse bestimmt die Eigenschaften und Fähigkeiten eines Objekts. Die in R-BASIC verfügbaren Klassen und deren Eigenschaften sind im "Objekt-Handbuch" beschrieben. Es ist durchaus vernünftig, sich zunächst eine Zeichnung anzufertigen. So kann man sich überlegen, wie die Programmoberfläche ungefähr aussehen könnte und wie viele und welche Objekte man benötigt. Außerdem kann man den wichtigsten Objekten jetzt schon einen aussagekräftigen Namen geben.

Prinzipiell sind Sie in der Wahl des Namens frei, es hat sich jedoch bewährt, den Namen aus zwei Teilen zusammenzusetzen. Der erste Teil beschreibt das Programm oder den Programmteil, zu dem das Objekt gehört. In unserem Fall wählen wir "Tutor". Der zweite Teil bezeichnet die Klasse, zu der das Objekt gehört. Das Primary Objekt heißt daher TutorPrimary, der Button heißt TutorButton usw. Das Datei-Menü ist auch ein Objekt. Es wird aber vom Primary-Objekt automatisch erzeugt, so dass wir uns darum nicht kümmern müssen.

Für unser Programm benötigen also wir 5 Objekte:

  1. Ein Objekt der Klasse "Number". Hier kann der Nutzer die Zahl eingeben.

  2. Ein Objekt der Klasse "Memo". Das ist ein Text-Objekt, mit dem wir das Ergebnis unserer Überprüfung anzeigen wollen.

  3. Ein Objekt der Klasse "Button". Das ist der Schalter, mit dem wir die Überprüfung starten wollen.

  4. Das eigentliche Programmfenster ist auch ein Objekt. Es gehört der Klasse "Primary" an.

  5. Zusätzlich benötigt jedes Programm ein unsichtbares Objekt der Klasse "Application". Dieses stellt die Verbindung zum GEOS-System her.
Alle Objekte sind miteinander verbunden. Man sagt, ein Objekt hat "children" (Kinder). Details zu Children und die Organisation von Objekten in Bäumen (Trees) finden Sie im Kapitel 2.1 (Objekte und Objekt-Bäume) des Objekt-Handbuchs.

In unserem Fall sieht die Verbindung, der sogenannte Objekt-Tree (Objektbaum), wie folgt aus. Zum Beispiel ist das Objekt TutorNumber ein child (Kind) des Objekts TutorPrimary. Im Gegenzug ist das Objekt TutorPrimary das parent (Eltern) des Objekts TutorNumber.

Es ist ganz wichtig, dass alle Objekte in den Objekttree eingebunden sind. Dazu gibt es die Anweisung "Children". Vergessen Sie das Einbinden eines Objekts in den Tree, so wird das Objekt nicht auf dem Bildschirm erscheinen. Es gibt darüber keine Fehlermeldung, da Sie nichts Verbotenes getan haben.

Alle Objekte werden im UI-Codefenster vereinbart. Das Application-Objekt hat genau ein Child, des Primary-Objekt.

Application TutorApplication
  Children = TutorPrimary
End OBJECT
Um ein Objekt anzulegen müssen Sie nicht jede Zeile einzeln tippen. Öffnen Sie stattdessen das Menü "Extras" -> "Code-Bausteine" -> "Neues Objekt". Dort finden Sie das Application-Objekt und auch alle anderen von uns benötigten Objekte. Sie brauchen nur noch die programmspezifischen Dinge ergänzen. Das Application-Objekt wird von uns nicht als Child eines anderen Objekts gesetzt, darum kümmert sich das System.

Nun legen wir das Primary-Objekt an und binden es in den Tree ein. Haben Sie daran gedacht, das Menü "Extras" -> "Code-Bausteine" -> "Neues Objekt" zu verwenden, um das Primaryobjekt anzulegen? Nachdem Sie das Objekt angelegt haben erscheint automatisch ein Dialogbox, die Sie beim Einbinden des Objekts in den Tree unterstützt.

Unser Primary-Objekt soll drei Children haben: das Number-Objekt, den Text und den Button. Es ist unter GEOS nicht üblich die Position der Objekte explizit anzugeben. Stattdessen geben wir an, wie die Objekte angeordnet werden sollen. Details zu diesem Thema finden Sie im Kapitel 3.3 (Geometriemanagement) des Objekt-Handbuchs. Wir wollen, dass die Children horizontal zentriert sind (justifyChildren = J_CENTER). JustifyChildren ist eine Instancevariable des Primaryobjekts. Instancevariablen können unterschiedliche Werte annehmen. In unserem Fall weisen wir ihr den Wert J_CENTER zu. J_CENTER ist eine numerische Konstante, d.h. J_Center steht symbolisch für eine Zahl. Die UI-Anweisung SizeWindowAsDesired bewirkt, dass das Primary nur so groß ist, wie unbedingt nötig. Probieren Sie ruhig aus, was passiert, wenn Sie eine oder mehrere dieser Zeilen auskommentieren (Ausrufezeichen davor schreiben).

Primary TutorPrimary
  Children = TutorNumber, TutorText, TutorButton
  justifyChildren = J_CENTER
  SizeWindowAsDesired
End OBJECT
Für das Number-Objekt setzen wir zur Demonstration ein paar Instancevariablen. Die Instancevariable Caption$ enthält Text, der das Number-Objekt näher beschreiben soll. Er erscheint direkt neben oder auf dem Objekt. Außerdem legen wir einen Startwert (value) sowie einen Minimal- und einen Maximalwert (minVal, maxVal) fest. Unser Numberobjekt stellt nur ganze Zahlen dar. Im Kapitel 4.7.2 (Display-Format) des Objekt-Handbuchs ist beschrieben, wie man Numberobjekte konfiguriert, damit sie Dezimalstellen darstellen können.
Number TutorNumber
  Caption$ = "Zahl eingeben:"
  value = 12
  minVal = -100
  maxVal = 100
End OBJECT
Das Ergebnis unserer Prüfung wollen wir in ein Textobjekt schreiben. Da der Nutzer dort nichts eingeben soll setzen wir das Textobjekt auf "nur Lesen", d.h. wir weisen der Instancevariablen readOnly den Wert TRUE zu. TRUE ist wieder eine numerische Konstante. Die UI-Anweisung TextFrame erzeugt einen Rahmen um das Objekt, der sonst bei read-only Objekten fehlt. Da wir noch keine Prüfung vorgenommen haben setzen wir als Anfangswert für den darzustellenden Text das Wort "ungetestet". Schließlich bewirkt die UI-Anweisung justifyText = J_CENTER, dass der Text zentriert dargestellt wird. Eine ausführliche Beschreibung der Textobjekte finden Sie im Kapitel 4.10 des Objekt-Handbuchs.
Memo TutorText
  text$ = "ungetestet"
  readOnly = TRUE
  TextFrame
  justifyText = J_CENTER
End OBJECT
Schließlich brauchen wir noch einen Button, mit dem wir die Prüfung der Zahl starten. Wenn wir den Button aktivieren wird eine spezielle Routine, der Actionhandler des Buttons, gestartet. Die Anweisung ActionHandler = CheckNumber legt fest, dass die Routine "CheckNumber", die wir noch schreiben müssen, gestartet werden soll, wenn wir den Button aktivieren. Button-Objekte sind im Kapitel 4.3 des Objekt-Handbuchs beschrieben.

Die Null in der Caption$ - Zeile legt fest, dass der Buchstabe an Position Null (hier das 'P') unterstrichen und zur Tastaturnavigation benutzt werden soll.

Button TutorButton
  Caption$ = "Prüfen", 0
  ActionHandler = CheckNumber
End OBJECT

^

3. Der Actionhandler

Nun müssen wir noch den Actionhandler des Buttons schreiben. Actionhandler sind spezielle Routinen, die direkt von einem Objekt aufgerufen werden. Actionhandler, die von einem Button aufgerufen werden, müssen als BUTTONACTION vereinbart werden. Auch hier benutzen wir das Menü "Extras" -> "Code-Bausteine" um den Actionhandler anzulegen (Unterpunkt "Action-Handler").
BUTTONACTION CheckNumber
DIM z                         ' z: zahl
  z = TutorNumber.value
  IF z/2 = Int(z/2) THEN
    TutorText.text$ = "gerade"
  ELSE
   TutorText.text$ = "ungerade"
  END IF
END ACTION
Die Zeile "z = TutorNumber.value" ist eine Zuweisung. Sie liest den Zahlenwert (value) des Numberobjekts aus und speichert ihn in der Variablen z. Man sagt, der Variablen z wird ein Wert zugewiesen. Z muss vorher mit DIM vereinbart worden sein.

Mit der IF-Anweisung können wir Entscheidungen treffen. Ist der zwischen IF und THEN stehende Ausdruck wahr, so werden die Anweisungen hinter THEN ausgeführt (in unserem Fall ist es nur eine Anweisung), andernfalls die hinter ELSE. End IF schließt den Entscheidungsteil. Das Kapitel 2.5.1 (Verzweigungen) des Programmierhandbuchs beschreibt die Möglichkeiten von R-BASIC, Entscheidungen zu treffen.

Um festzustellen, ob die Zahl gerade ist vergleichen wir die Hälfte der Zahl (z/2) mit dem ganzzahligen Anteil (Funktion Int(..)) der halben Zahl. Ist zum Beispiel z = 5, so ist z/2 = 2,5 und Int(z/2) = 2. Die Werte sind nicht gleich, z ist ungerade. Einen Überblick über die in R-BASIC verfügbaren mathematischen Funktionen finden Sie im Kapitel 2.3.1 (Überblick über numerische Funktionen) des Programmierhandbuchs.

Die Anweisung TutorText.text$ = "...." weist dem Textobjekt einen neuen Text zu, der sofort angezeigt wird. Zeichenketten (genannt Strings) werden in " " eingeschlossen, Stringvariablen werden üblicherweise durch ein angehängtes $ gekennzeichnet. Das ist Ihnen bestimmt schon bei Caption$ aufgefallen.

Nachdem Sie das Programm eingetippt und gestartet haben sollten Sie damit herumspielen. Ändern Sie einzelne Codezeilen oder kommentieren Sie sie aus. Überlegen Sie vorher, was passieren wird und vergleichen Sie Ihre Vorhersagen mit dem erreichten Ergebnis.

^

4. Erste Verbesserungen

Wir wollen nun unser Programm etwas verändern, indem wir die Eingabe der Zahl nicht über ein Numberobjekt, sondern über ein Textobjekt machen. Das sieht besser aus und "Drag'n Drop" funktioniert auch.

Dazu verwenden wir die andere Textobjektklasse, über die R-BASIC verfügt. Das Objekt InputLine stellt einen einzeiligen Text bereit. Mit der Anweisung "justifyCaption = J_TOP" verschieben wir die Aufschrift über das Objekt. Captions sind sehr vielseitig. Sie können nicht nur Text sondern auch Grafiken enthalten. Details dazu finden Sie im Kapitel 3.1 (Caption: Die Objekt-Beschriftung) des Objekt Handbuchs.

InputLine TutorInputText
  Caption$ = "Zahl eingeben:"
  justifyCaption = J_TOP
  text$ = "12"
  backColor = WHITE
  textFilter = TF_SIGNED_NUMERIC + TF_NO_SPACES
End OBJECT
Der Startwert (text$ = "12") ist natürlich keine Zahl, sondern ein String. Mit "backColor = WHITE" machen wir den Texthintergrund weiß. WHITE ist eine numerische Konstante (ein Symbol für eine Zahl). R-BASIC hat für alle 16 Standardfarben eine entsprechende Konstante. Näheres zur Beschreibung von Farben finden Sie im Kapitel 2.8.2 (Farben) des Programmierhandbuchs.

Von besonderer Bedeutung ist für unsere Anwendung die Zeile "textFilter = TF_NUMERIC + TF_NO_SPACES". Textfilter sind eigentlich etwas für Fortgeschrittene, aber an dieser Stelle sehr hilfreich. Ein Textfilter weist das Objekt an, nur bestimmte Zeichen zu akzeptieren. In unserem Fall sind die Werte TF_SIGNED_NUMERIC (nur Ziffern, Minus und Leerzeichen) kombiniert mit TF_NO_SPACES (keine Leerzeichen) angebracht. Das Setzen eines Textfilters erspart uns bei der Auswertung die Aufwändige Prüfung, ob der Nutzer überhaupt eine Zahl und nicht etwa "Paul" oder "eins" eingegeben hat. Textfilter sind im Kapitel 4.10.5 (Textfilter) des Objekthandbuchs beschrieben.

Bitte vergessen Sie nicht, das neue Objekt anstelle des Number-Objekts als Child des Primary-Objekts einzutragen.

Natürlich müssen wir jetzt unsere Auswerteroutine anpassen. Insbesondere müssen wir den vom Nutzer eingegebenen Text in eine Zahl umwandeln. Diese Aufgabe erledigt die Funktion Val(...). Val steht für das englische Wort value (Wert). "t$ = TutorInputText.text$" speichert zuvor den vom Nutzer eingegeben Text in der Stringvariablen t$. Die DIM-Anweisung erkennt an dem angehängten $-Zeichen, dass die Variable einen Text und keine Zahl aufnehmen soll.

BUTTONACTION CheckNumber
DIM z, t$' zahl, text
  t$ = TutorInputText.text$
  z = Val(t$)
  IF z/2 = int(z/2) THEN
    TutorText.text$ = "gerade"
  ELSE
    TutorText.text$ = "ungerade"
  END IF
END ACTION
Tipp: Da die Variable t$ nirgends weiter gebraucht wird kann man sie auch einsparen. Die ersten beiden Zeilen werden dann zu:
  z = Val( TutorInputText.text$ )
Details zu Variablen und den zugehörigen Datentypen finden Sie weiter unten, im Kapitel 2.2 (Variablen und Typen). Der leichte Umgang mit Zeichenketten (Strings) gehört zu den großen Stärken der BASIC-Syntax. Einen Überblick über die in R-BASIC zur Verfügung stehenden Stringfunktionen finden Sie im Abschnitt 2.4.1 des Programmierhandbuchs.

^

5. Weitere Änderungen

Nun möchten wir die am Anfang eingestellte Zahl durch eine zufällig ausgewählte Zahl ersetzen. Dazu benötigen wir eine Routine, beim Programmstart automatisch ausgeführt wird. Das ist eine sehr häufig auftretende Situation. In R-BASIC ist das so gelöst, dass wir dem Application-Objekt einen "OnStartup" Handler geben. Wir nennen ihn "AppStartup". Wir hätten ihn auch "Paul" nennen können, aber die Namenswahl AppStartup enthält gleichzeitig einen Hinweis darauf, was der Handler tun soll. Das ist prinzipiell immer eine gute Idee. Der UI-Code des Application-Objekts sieht jetzt also so aus:
Application TutorApplication
  Children = TutorPrimary
  OnStartup = AppStartup
End OBJECT
Das Application-Objekt ist im Kapitel 4.1 des Objekthandbuchs beschrieben. Es bietet zum Beispiel die Möglichkeit einem Programm ein eigenes Token (Icon) zu geben und vieles mehr.

Unser AppStartup Handler muss als SYSTEMACTION vereinbart werden. Je nachdem, ob wir das Number-Objekt TutorNumber oder das InputLine-Objekt TutorInputText zur Eingabe der Zahl verwenden fällt der Handler geringfügig anders aus.

Wir schauen uns zunächst die Variante mit dem Number-Objekt an.

' Variante  mit Number-Objekt
SYSTEMACTION AppStartup
DIM z' zahl
  Randomize
  z = Int( 100 * Rnd() )
  TutorNumber.value = z
END ACTION
Als erstes initialisieren wir mit der Anweisung Randomize den Zufallsgenerator. Das sollte jedes Programm, das mit Zufallszahlen arbeitet, tun.

Die Funktion Rnd() liefert eine Zufallszahl x im Bereich 0 <= x < 1. Wenn wir unsere Zufallszahl z im Bereiche 0 <= z < 100 haben wollen müssen wir diesen Wert mit 100 multiplizieren. Die Funktion Int() (Int steht für Integer, ganzzahlig) schneidet die Nachkommastellen ab. Die Zeile z = Int( 100 * Rnd() ) weist also der Variablen z eine Ganze Zahl im Bereich zwischen 0 und 99 zu.

Schließlich weisen wir mit der Anweisung TutorNumber.value = z dem Objekt TutorNumber den Wert der Variablen z zu. Das Objekt zeigt diesen Wert sofort an.

Wenn wir das Textobjekt zur Eingabe der Zahl verwenden sieht der Handler so aus:

SYSTEMACTION AppStartup
DIM z' zahl
  Randomize
  z = Int( 100 * Rnd() )
  TutorInputText.text$ = Str$(z)
END ACTION
Wir sehen, dass sich nur die letzte Zeile unterscheidet. Zunächst heißt die Instancevariable, die wir belegen müssen, bei einem Textobjekt "text$". Diese enthält natürlich eine Zeichenkette (einen String) und keine Zahl. Deswegen müssen wir die Zahl z mit der Funktion Str$() in eine Zeichenkette umwandeln.

Das ist schon alles.

^

Zusammenfassung

  • Jedes BASIC Programm besteht aus den Objekten und dem eigentlichen BASIC Code.

  • Die Objekte sind in einer Parent-Child-Struktur miteinander verbunden.

  • Man benötigt auf jeden Fall ein Application-Objekt und ein Primary-Objekt.

  • Der Programmcode wird in Form von Actionhandlern realisiert.

  • Actionhandler werden aufgerufen wenn der Nutzer eine Aktion auslöst.

Tipps

  • Programmieren lernt man nicht durch Lesen, sondern durch Programmieren. Spielen Sie ruhig an den Programmen herum. Ändern Sie etwas, lassen Sie Anweisungen weg und sehen Sie, welche Auswirkungen das hat.

  • Wenn Sie sich mit einem neuen Problem beschäftigen, schauen Sie in die Beispiele. R-BASIC liefert zu nahezu allen Befehlen, Instancevariablen und Objekten Programmbeispiele mit.

  • Es ist völlig normal, dass Sie beim Lesen der Dokumentation vieles nicht auf den ersten Blick verstehen. PC/GEOS Objekte sind wunderbar intelligent und vielseitig einsetzbar. Entsprechend kompliziert sind einige Stellen der "Bedienungsanleitung" (Dokumentation). Sie brauchen fürs Erste nur das zu verstehen, was sie gerade benutzen wollen.

  • Suchen Sie sich für den Anfang einfache, überschaubare Projekte. Viele Programmierer haben mit einem Lottozahlengenerator oder etwas ähnlichem angefangen.
Beherzigen Sie nach Möglichkeit die folgenden Ratschläge:
  • Machen Sie sich im Vorfeld eine Plan, was das Programm genau können soll und was es nicht können soll.

  • Verwenden Sie aussagekräftige Namen für Variablen, Objekte und Routinen. Ein Textobjekt, in das der Nutzer etwas eingeben soll, könnte "EingabeText" heißen. Nennt man es nur "Eingabe" könnte man später in Zweifel kommen, ob man das Textobjekt oder den eigegebenen Text meint.

  • Verwenden Sie großzügig Kommentare. Kommentieren Sie vor allem die Ideen hinter einem Programmabschnitt. Das Notieren einer Idee hilft Ihnen, das Problem gut zu durchdenken und verringert so die Fehlerquote.

^

Weiter...