Mobile Times Business Club
Startseite : Mobility : OPL Kurs
OPL OPL Kurs, Teil 3 Aktualisierung
2007-03-01
01: Einführung
02: Menüs und mehr
03: Basics, Zufall & Mathetrainer
04: Spielend lernen - Würfel, Bandit & Lotto
05: Datenbanken - Neu/Ändern/Löschen
06: Datenbanken - Suchen/Gehen Zu
07: Gezielte Textausgabe
08: Fensterl'n mit dem Psion
09: Zeichnen mit Grips
Basics, Zufall & Mathetrainer
Wie viele Psionbenutzer wissen. besitzt der Psion eine integrierte Programmiersprache: OPL. Wir werden im Rahmen dieses Kurses nicht nur zeigen, wie mächtig OPL tatsächlich ist, sondern Ihnen auch nachvollziehbare Beispiele, die für Ihre Praxisanwendungen vorbereitet sind, für Ihre eigene Programmierung mitgeben.
    Bei OPL handelt es sich um eine Interpretersprache (wie z.B.: Visual Basic), dessen Programme in 3 Stufen erstellt wird.
* Eingabe des Programms
* Übersetzen des Programms
* Ausführen des Programms (falls das Programm nicht funktioniert, können diese Schritte beliebig oft wiederholt werden).

Prozeduren
Wie bei jeder Programmiersprache wollen wir auch in diesem Beispiel das klassische Einsteigerprogramm abdrucken:
Pro 1
proc main:
   print "Hallo Psion-User"
   print "Taste drücken = Programmende"
   get
endp
    Anhand dieses einfachen Programme, welches am Schirm des Psion zwei Textzeilen ausgibt und anschließend mit GET auf einen Tastendruck wartet, sieht man den Aufbau einer Prozedur. Prozeduren sind abgegrenzte Programmblöcke, die einfach eine Organisationsform fürs Programmieren darstellen.
    Jede Prozedur hat einen Namen und wird folglich PROC Name: begonnen. Beendet wird eine Prozedur mit ENDP. Wenn Sie sich von der Funktion des Programms überzeugen wollen, geben Sie es am besten gleich ein. Lassen Sie es danach übersetzen und beantworten Sie die Frage, ob es gestartet werden soll mit ja. Diese einfachen Programme laufen auf allen Psions!
    Ein OPL Programm wird meist in mehrere Prozeduren (auch "Module" genannt) aufgeteilt Bei komplexeren Programmen ist es nämlich sinnvoll, die Aufgabe in Teile zu zerlegen und auf mehrere kleinere Prozeduren aufzuteilen, weil dadurch die Übersichtlichkeit steigt.
    Um dies wieder an einem Beispiel zu zeigen:
Pro 2
proc main:
   Hallo:
   print "Taste drücken = Programmende"
   get
endp
proc Hallo:
   print "Hallo Psion-User"
endp
    In diesen Programm haben wir die Aufgabe "Hallo Psion-User" auf dem Bildschirm auszugeben, in die Prozedur Hallo: verlegt. Das sichtbare Ergebnis des zweiten Programms ist das gleiche wie beim ersten. Man kann sehr deutlich den Aufruf der Prozedur Hallo: (mit Doppelpunkt!) erkennen. Das Programm startet bei Zeile 1 und enthält in Zeile 2 die Sprungmarke zu einer Prozedur (in unserem Fall Hallo:). In der 2. Prozedur gibt das Programm "Hallo Psion-User" auf den Bildschirm aus, kehrt wieder in die erste Prozedur zurück und setzt dort das Programm in Zeile 3 fort.
    Nun kann jede Prozedur Werte an eine aufgerufene Prozedur mitgeben, die in der angerufenen Prozedur verarbeitet werden. Z.B.:
Pro 3
proc main:
   local str$(20)
   str$ = "Hallo Psion-User"
   Hallo:(str$)
   print "Taste drücken = Programmende"
   get
endp
Das Ergebnis ist wider Erwarten dasselbe, wie bei den ersten beiden Programmen. Um dieses Programm laufen zu lassen zu können, wurde zusätzlich eine Variable deklariert.

Variablen
Bei Variablen handelt es sich um Speicherplätze (vergleichbar mit Schubladen), in denen Werte (Zahlen, Buchstaben...) "aufbewahrt" werden können. Will man diese Werte erneut verwenden, kann man an ihrer Stelle ersatzweise auch die Variablen verwenden. Diese Variablen müssen, bevor man sie im Programm verwendet, deklariert werden. Das bedeutet, daß Variablen vom Programm eben jener erforderliche Speicher reserviert wird. Die Variablen bekommen Namen. Die dürfen maximal 7 Buchstaben lang sein und werden mit bestimmten Nachzeichen (Suffix) deklariert.
Einfache Variablen:
* var ist eine Fließkommavariable, in der beliebige Zahlen gespeichert werden können
* var% ist eine Integervariable, in der ganze Zahlen gespeichert werden können
* var$(Zahl) ist eine Stringvariable, in der Zeichen gespeichert werden können. Bei "Zahl" wird die Anzahl der Zeichen angegeben, welche in der Variablen maximal gespeichert werden.
Felder
Ein Feld ist eine Variable, die mehrere Werte des gleichen Typs speichern kann. Sie können z.B.: in einem Feld, das wie folgt aussieht: feld%(5), insgesamt 5 Integerwerte speichern. Bei Strings sieht das z.B.: so aus: feld$(5,10). Die zweite Zahl kommt daher, daß für einen String neben der Anzahl der Felder auch die maximal speicherbaren Zeichen pro Speicherplatz mit angegeben werden müssen. In diesem Falle können 5 Strings mit maximal 10 Zeichen gespeichert werden.
Deklaration und Wertzuweisung
Die Deklaration einer Variable erfolgt zu Anfang jedes Programms. rem leitet einen Kommentar ein, der bei er Übersetzung des Programms nicht verwendet wird, aber der eigenen Übersicht (insbesondere bei komplizierten Programmabschnitten) hilft.
Pro 4
proc test:
   local a%, b%, c%, str$(15)
   a% = 1
      rem Zuweisung von 1 zur Variablen a%
   b% = 2
   c% = a% + b%
      rem Die Summe der Werte der
      rem Variablen a% und b% werden
      rem der Variablen c% zugewiesen
   str$ = "1 + 2 = 3"
   print str$
   get
endp
Das Ergebnis auf dem Bildschirm sieht so aus:
1 + 2 = 3
    Anhand dieses Programms sieht man die Deklaration von Integer- und Stringvariablen und danach eine Wertzuweisung bei a% und b%. Anschließend wird c% die Summe von a% und b% zugewiesen. In str$ wird eine Zeichenfolge mit der Rechenoperation und dem Ergebnis gespeichert und dann mit PRINT auf dem Bildschirm ausgegeben. Der Begriff "LOCAL" bedeutet, daß die Variablen nur für diese Prozedur gültig sind. Sollen Sie einen weiteren Wirkungskreis haben, deklariert man ihren Gültigkeitsbereich "GLOBAL".
    Soweit die erste Basis, auf die die weiteren Dinge aufsetzen können. Damit ein Programm überhaupt sinnvolle Dinge tun kann, muß man es einerseits in der Lage sein, stur Befehl um Befehl abzuarbeiten (zur Not auch mehrfach im Kreise), als auch andererseits aufgrund von Entscheidungen verzweigte Wege zu gehen. Die Verfügung stehenden Methoden beschreiben wir nun.

Schleifen und Verzweigungen
Beim Programmieren ist es notwendig und sinnvoll, gleichzeitig immer wiederkehrende Anweisungen nicht einzeln zu schreiben, sondern diese Operationen in Schleifen (Wiederholung von Anweisungen), Verzweigungen (ausführen von alternativen Anweisungen) oder, wie schon gezeigt, mit Sprungmarken in Prozeduren zu legen.
    Für Schleifen gibt es in OPL zwei Befehle:
DO..UNTIL
Beispiel:
Pro 5
PROC Main:
   local a%
   a% = 100
   do
      print "a% = ";a%
      a% = a% + 20
   until a% = 500
   print "Ende der D O . . U N T I L  Schleife"
   get
ENDP
In diesem Beispiel erkennt man den Sinn von Schleifen. Würde es keine Schleifen geben, könnte man das Problem auch lösen, allerdings wäre viel mehr Programmierarbeit notwendig und der Sourcode wäre erheblich größer.
    Bei der DO..UNTIL Schleife wird die Bedingung am Ende der Schleife geprüft. Diese Schleife läuft solange bis eine Bedingung erfüllt (a% = 500) wird. VORSICHT: Ihr Programm kann abstürzen (hängen bleiben) falls in einer Schleife die Bedingung nie erfüllt wird (Endlosschleife). Gelegentlich sind solche Endlosschleifen aber auch von Nutzen. Doch darüber reden wir erst später.
WHILE..ENDWH
Beispiel:
Pro 6
PROC Main:
   local a%
   a% = 1
   while a% < 61
      print "a% = ";a%
      a% = a% + 3
   endwh
   print "Ende der W H I L E . . E N D W H  Schleife"
   get
ENDP
Das markante der WHILE..ENDWH Schleife ist: Die Bedingung, die die Schleife steuert, wird bereits an ihrem Anfang geprüft. In unserem Beispiel wird die Schleife solange ausgeführt wie die Bedienung erfüllt wird: "Gebe solange Werte von a% auf dem Bildschirm aus wie der Wert von a% kleiner als 61 ist".
Verzweigungen per IF..ELSEIF..ELSE..ENDIF
In einem Programm sind sehr oft wichtige Entscheidungen für den weiteren Programmverlauf zu tätigen, die zum Arbeiten alternativer Anweisungen führen. Hier eignet sich die IF..ELSEIF..ELSE..ENDIF Verzweigung. Eine IF..ENDIF Verzweigung beginnt immer mit IF-Bedingung und endet immer mit ENDIF. Die Befehle ELSEIF und ELSE können optional eingefügt werden.
Beispiel:
Pro 7
PROC Main:
   local a%
   a% = 1
   while a% <11
      if a% = 1
         print a%
      elseif a% = 5
         print a%
      elseif a% = 3 or a% = 7
         print a%
      else
         print "a% = ";a%
      endif
      a% = a% + 1
   endwh
   print "Ende des Programmes"
   get
endp
    Die IF..ENDIF Verzweigung kann auch in Schleifen eingebaut werden. Man sieht deutlich, daß in der Schleife die Werte a% nochmals geprüft werden. Der ELSEIF Befehl kann beliebig oft in eine IF..ENDIF Konstruktion eingebaut werden. Es ist allerdings darauf zu achten, daß bei einer IF..ENDIF Verzweigung immer nur eine Bedingung ausgeführt wird. Trifft also eine Bedingung zu, dann springt des Programm nach der folgenden Anweisung (z.B.: PRINT a%) ans Ende hinter ENDIF. Wird keine der Bedingungen erfüllt, so wird auf ELSE verzweigt und die Anweisung zwischen ELSE und ENDIF ausgeführt. Sollte keine ELSE vorhanden sein und der IF..ENDIF Konstruktion wird keine Bedingung erfüllt, dann passiert nichts und das Programm setzt nach der Verzweigung fort.
    Mit diesen wenigen Informationen verfügen Sie nun über die wesentlichen "Geheimnisse" eines Programmierers. Nicht, daß es da nicht noch mehr zu wissen gäbe, aber Programme leben einfach von den eben beschriebenen Verfahren. Lassen Sie sich auf keinen Fall entmutigen. Mit steigender Programmierübung wächst auch Ihre Erfahrung mit OPL massiv. Wir werden Sie begleiten.

Programmbeispiel: Mathe-Trainer:
Beginnen wir mit der Vertiefung des eben Gelernten anhand eines kleinen Programms, das ausbaufähig ist. Anhand eines Zufallsgenerators werden 2 Zahlen von 1 bis 10 erzeugt, die auf dem Bildschirm dargestellt werden. Sie sollen die Zahlen im Kopf multiplizieren und das Ergebnis eingeben. Das Programm überprüft dann, ob Sie das kleine Einmaleins noch beherrschen.
    Sie lernen dabei neue OPL-Funktionen und -Befehle kennen, die wir reichlich kommentieren werden, damit Sie die Schritte auch nachvollziehen können. Weil die Kommentare etwas länger ausfallen können, werden sie nach dem OPL-Code angeordnet. Für den Anfang verzichten wir auf "Schönheit" in der Bildschirmausgabe. Es geht uns erst mal um die Prinzipien.
    Wir haben das Programm auf drei Prozeduren verteilt. Beginnen wir mit dem Hauptprogramm. Sofern man den Programmtext direkt auf dem Psion eingibt und mit mehreren Prozeduren arbeitet, ist immer die "oben" stehende erste Prozedur der Programmteil, der vom Psion auch zuerst abgearbeitet wird.
    Die von uns verwendete Variable zahl%() ist eine Feldvariable. Damit sie von allen weiteren Programmteilen benutzt werden kann (sie wird von mathe: und zufall: benötigt), haben wir sie GLOBAL deklariert. Die Anzahl der Felder ist hier zu "7" festgelegt und absichtlich etwas überdimensioniert, damit wir die Variable auch in Folgeprogrammen gleich so weiterverwenden können.
    Da wir mit dem Zufallsgenerator arbeiten wollen, versetzen wir diesen gleich zu Programmbeginn in einem Grundzustand. Dazu wird der Befehl RANDOMIZE... in Verbindung mit der Systemzeit verwendet. Das sichert, daß bei erneutem Programmstart tatsächlich jedesmal andere Zufallszahlen generiert werden.
Pro 8
PROC main:
   global zahl%(7)
   randomize minute + second
   mathe:
   cls              rem Löscht den gesamten Bildschirm
   print : print    rem erzeugt zwei Leerzeilen, 
                    rem damit die erste Zeile nicht
                    rem am oberen Bildschirmrand
                    rem klebt
   print "Programmende. Taste drücken"
   get              rem gibt den Text aus und wartet auf
                    rem einen beliebigen Tastendruck
ENDP
    Die Prozedur main: übernimmt lediglich eine dirigierende Aufgabe und verteilt die gestellte Programmieraufgabe an das Modul mathe:. Sowie das Modul mathe: seine Aufgabe erledigt hat, übernimmt main: wieder die Kontrolle und fährt mit CLS usw. fort. Die Schreibweise PRINT : PRINT zeigt, daß man durchaus zwei (oder mehr) Anweisungen in eine Zeile schreiben kann, wenn man sie durch einen Doppelpunkt voneinander trennt. Üblicherweise tippt man aber jede Programmanweisung in eine Zeile - das macht es am Ende einfach übersichtlicher.
Pro 9
proc mathe:
   local eingabe%
   do
      cls
      zufall: (2,10)
      print : print
      print "Berechne:",zahl%(1),"*",zahl%(2)
      print "Gib das Ergebnis ein!"
      print "(Null beendet das Programm)"
      input eingabe%
      if eingabe% = zahl%(1) * zahl%(2)
         print "Ja!. Das ist richtig CLAUDIA!"
      else
         print "Nein! Das ist falsch CLAUDIA!"
      endif
      if eingabe% <> 0
         print "Beliebige Taste drücken"
         get
      endif
   until eingabe%=0
endp
    In diesem Fall wird in der DO..UNTIL-Schleife nicht gezählt und der Abbruch nach einer bestimmten Anzahl von Durchläufen gestoppt sondern auf eine bestimmte, von außen eingefügte Bedingung gewartet. Nur wenn diese erfüllt wird, verläßt das Programm die Schleife. So können Sie die Mathe-Übung nach eigener Lust und Laune fortführen oder abbrechen.
    Die folgende Prozedur zufall: wurde auf Erweiterbarkeit angelegt. Daher muß man an sie beim Aufruf Werte ("Parameter") übernehmen. Anhand der Parameter verhält sie sich dann unterschiedlich. Im Fall unseres Matheprogramms sollen zwei Zufallszahlen erzeugt werden. Die größte dabei vorkommende Zahl soll "zehn" sein. Deshalb übergibt die Prozedur mathe: eben diese Zahlen. Die Prozedur zufall: nimmt die Parameter dann genau in der Reihenfolge wieder auf und weist sie eigenen Variablen zu, deren Gültigkeit sich auf diese Prozedur beschränkt. Die Variablen werden durch die vorgeschriebene Schreibweise praktisch automatisch deklariert.
Pro 10
proc zufall:(anzahl%,max%)
   local n%
   n%=1
   while n%<= anzahl%
   zahl%(n%)=1+int(rnd * max%)
   n%=n%+1
   endwh
endp
    In unserem Mathe-Beispiel wäre es durchaus einfacher gewesen, die Zufallszahl durch die Progammzeilen
Pro 11
zahl% (1)=1+int(rnd*10)
zahl% (2)=1+int(rnd*10)
zu erzeugen. Aber bereits ab sechs zu erzeugenden Werten lohnt sich der Aufbau der hier verwendeten Schleife.
    Die Funktion RND erzeugt eine Zufallszahl vom Typ Floating Point zwischen 0 (einschließlich) und 1 (ausschließlich). Multipliziert man daher den erhaltenen Wert mit 10, bekommt man ein Spektrum von Null bis 9.9999.. Für unseren Zweck benötigen wir eine Ganzzahl (Integer), die wir uns durch die Anwendung von INT berechnen lassen. INT scheidet alles hinter dem Komma einer Fließkommazahl ab, so daß in unserem Beispiel Werte von Null bis 9 anfallen. Die Addition von eins ändert diesen Bereich auf 1 bis 10 - genauso wollten wir es haben!
    Sie sollten für dieses Mal genügend Stoff zum Ausprobieren zu Verfügung haben. Variieren Sie einfach ein wenig und schauen Sie sich jeweils das Ergebnis an. Sie wissen schon: Übung macht den Meister. Viel Vergnügen!


OPL am Psion von Rudolf Pöchacker (http://members.xoom.com/poechacker/)
Valid HTML 4.01! Copyright © 2002-2007 Mobile Times Business Club
Zurück zum Menü
Nach Oben