Einleitung

Bearbeiten

Die Programmiersprache REXX kennt keine Typendeklaration.

Wenn eine Variable noch keinen Wert zugewiesen bekommen hat, also uninitialisiert ist, verhält sie sich wie ein in Großbuchstaben geschriebener String:

say hallo => HALLO

Erst mit der Initialisierung ändert sich das:

hallo = 25
say hallo             =>  25
hallo = "say 5 + 3"
say hallo             =>  say 5 + 3

Durch die Anweisung drop wird eine Variable deinitialisiert und vergessen.

hallo = "Guten Morgen"
say hallo              =>  Guten Morgen
drop hallo
say hallo              =>  HALLO

Werden in REXX Variablen mit Zahlen initialisiert, läßt sich mit ihnen rechnen:

a = 25
b = 17
say a + b => 42
say a - b => 8
say a * b => 425

Stems haben in vielerlei Hinsicht Ähnlichkeiten mit Arrays:

do i = 1 to 10
   zahl.i = 10 - i
end
zahl.0 = i - 1     /* => 10; per Konvention */

do i = 1 to zahl.0
   say i')' zahl.i
end i

Danach existieren folgende Variablen mit folgender Zuordnung: zahl.1 = 9, zahl.2 = 8, zahl.3 = 7 ... Per Konvention wird unter dem Index 0 die Anzahl der gespeicherten Elemente abgelegt. Mit drop zahl. können dann alle elf Variablen der Form zahl.i mit einem Schlag entfernt werden.

Andererseits haben Stems auch Ähnlichkeiten mit Zeigern (Pointern):

a = 2
Do 5
b = 2*a-1
p.a = b
a = b
End

Nach dem Ablauf existieren folgende Variablen mit folgender Zuordnung: p.2 = 3, p.3 = 5, p.5 = 9, p.9 = 17, p.17 = 33. Wie bei Zeigern läßt sich, ohne explizit die Existenz der Variablen (mit Ausnahme der ersten Variable p.2) zu kennen, auf die verketteten Variablen zugreifen.


Diese Art der Variablen wird als Stem-Variablen bezeichnet; der erste Teil einschließlich des ersten Punkts wird als Stem bezeichnet, der Rest als Tail. Der Tail kann auch aus mehreren Symbolen bestehen, die durch Punkte voneinander getrennt werden; auf diese Weise können auch mehrdimensionale Arrays realisiert werden. Die Werte der verwendeten Symbole können beliebig sein; sie sind durchaus nicht auf Zahlen beschränkt.


  • Ausgabe über den Bildschirm

Wenn man in REXX etwas über den Bildschirm ausgeben will, macht man das über die Anweisung say:

say ausdruck
  • Ausgabe als Datei
lineout(dateiname,ausdruck)
  • Eingabe über die Tastatur

Die Eingabe über die Tastatur erfolgt über die Anweisung pull:

pull variable
  • Eingabe aus einer Datei
variable=linein(dateiname)

Wenn man sicher gehen will, dass im Eingabestrom noch Zeilen vorhanden sind, kann man die Funktion lines() verwenden:

variable = lines(dateiname)

Der zurückgelieferte Wert gibt an, wieviele vollständige Zeilen sich noch im Eingabestrom befinden.

Für den Fall, dass man einzelne Zeichen lesen will, gibt es die zu linein() und lines() analogen Funktionen charin() und chars()

charin(dateiname)
variable = chars(dateiname)
  • Übergabe bei Start eines REXX-Programms

Wie bei den meisten Programmiersprachen, lassen sich beim Start eines Programms Parameter übergeben. Das Programm kann diese Parameter über die Funktion arg(1) abrufen und dann wie einen String auswerten.

/* Ein REXX-Program */
console = arg(1)
say
anzahl = words(console)
do index = 1 to anzahl by 1
  say word(console,index)
end

Der Aufruf von arg() liefert zurück, ob Parameter angegeben wurden (arg() == 1) oder ob keine Parameter angegeben wurden (arg() == 0).


Mathematische Grundoperationen

Bearbeiten
  • Addieren:
a = 2+3 ==> a == 5
  • Multiplizieren:
a = 2*3 ==> a == 6
  • Subtrahieren:
a = 2-3 ==> a == -1
  • Division:
a = 2 / 3 ==> a == 0.66667
  • Potenzieren:

Um bn zu berechnen benutzt man b**n

a = 2**3 ==> a == 8

Man kann nicht alles so teilen, das gebrochene Zahlen herauskommen. Wenn man zum Beispiel 33 Eier auf 4 Personen aufteilen will, ohne die Eier zu zerteilen, so bleiben Eier übrig. Die Aufteilung ist in diesem Fall 7 Eier pro Person, und 5 Eier, die man nicht aufteilen kann. Die Operationen heißen Div und Mod, und werden in REXX durch die Symbole % und // repräsentiert.

  • Div
a = 33 % 4 ==> a == 7
  • Mod
a = 33 // 4 ==> a == 5

Die Modulo-Operation spielt in der Zahlentheorie eine besondere Bedeutung. Der kleine fermatsche Satz besagt nämlich, das wenn die natürliche Zahl   eine Primzahl ist, dann gilt für jede Basis  , das   durch   teilbar ist. Daraus abgeleitet gilt für jede Primzahl  :  .

In einem Programm in REXX wird man diesen Satz so verwenden:

n = (a**(p-1))//p ==> wenn n == 1 ist, dann ist p mit einer gewissen Wahrscheinlichkeit eine Primzahl.

in der Praxis benötigt man die Modulo-Operation sehr oft für Datumsberechnungen. z.B. 26.01.2006 war Mitwoch. der 27.04.2006 ist genau 90 Tage später. 90 % 7 = 6 (90:7=84 Rest 6) Daraus folgt, Mittwoch + 6 Tage = Dienstag

logische Funktionen

Bearbeiten

Die folgenden drei Funktionen vergleichen die Zeichen bitweise. Ein Bit kann dabei den Zustand 0 oder 1 haben. Jeweils 8 Bit zusammengefasst ergeben ein Zeichen. Das Zeichen "A" hat zum Beispiel den entsprechenden binären Code 01000001.

  • bitand(a,b)

Beispiel: 01011010 und 01101101 ergeben 01001000

a = bitand("Z","m") ==> a == "H"
  • bitor(a,b)

Beispiel: 01011010 und 01101101 ergeben 01111111

a = bitor("Z","m") ==> 
  • bitxor(a,b)

Beispiel: 01011010 und 01101101 ergeben 00110111

a = bitor("Z","m") ==> "7"

Um diese Operationen mit dezimalen Zahlen benuzten zu können, muß man sie vorher und nachher konvertieren:

a = D2C(5)
b = D2C(9)
x = C2D(bitand(a,b)) ==> x ==  1
y = C2D(bitor(a,b))  ==> y == 13
z = C2D(bitxor(a,b)) ==> z == 12

Einleitung

Bearbeiten

Der eigentliche Typ einer Variable in REXX ist ja String. Demzufolge gibt es eine Menge Anweisungen und Funktionen zur Bearbeitung von Strings.

Konkatenation

Bearbeiten

Es kommt vor, das man zwei Strings (oder mehr) zu einem String zusammenführen, oder einen String verlängern möchte. So eine Zusammenführung ermöglicht der Operator ||:

gesamtstring = string1||string2

Länge eines Strings

Bearbeiten

Mit der Funktion length() bekommt man heraus, aus wie vielen Zeichen ein String besteht:

variable = length(string)

Teilstrings

Bearbeiten

Manchmal will man nur einen Teil eines Strings verwenden. Dafür kann man die Funktion substr() verwenden:

teilstring = substr(string,startposition,länge)

Beispiel: a = substr("Grottenolm",2,5) => a == "rotte"

Wörterzerlegung

Bearbeiten

Angenommen, man will die Wörter eines als String eingegebenen Satzes analysieren. Dafür gibt es eine Anzahl von Funktionen. Die Funktion words() gibt die Anzahl der Wörter zurück, aus denen der String zusammengesetzt ist:

variable = words(string)

Beispiel: a = words("Dieser Satz hat fünf Wörter") => a == 5

Mit der Funktion word() kann man dann auf die einzelnen Wörter dieses Strings zugreifen:

variable = word(string,wert)

Beispiel: a = word("Die Katze tritt die Treppe krum",2) => a == "Katze"

Sonstiges

Bearbeiten

Beispiel: a = lower("HaLlO") => a == "hallo"

Beispiel: a = upper("HaLlO") => a == "HALLO"


Einleitung

Bearbeiten

Alle Anweisungen und Funktionen, die nicht schon in den anderen Kapiteln besprochen wurden oder noch besprochen werden, werden hier behandelt.

Anweisungen

Bearbeiten
  • clear

Die Anweisung clear löscht den Bildschim.


  • drop

Mit drop variable kann man einzelne Variablen löschen, oder auch einen ganzen Stem.

  • exit

Die Anweisung exit veranlaßt ein Programm sich zu beenden.


  • leave

leave bewirkt das Verlassen einer Schleife. Das ist besonders sinnvoll, wenn es sich bei der Schleife um eine Endlosschleife handelt.

  • nop

Die Anweisung nop steht für no operation. Es ist eine Leeranweisung, die nichts macht.

  • random(u,o,s)

Um Zufallszahlen zu bekommen, kann man Die Funktion random() verwenden. random kennt die drei Parameter u (für Untergrenze), o (für Obergrenze und s. Alle drei Parameter sind optional, können also auch entfallen.

  • C2D()

C2D() wandelt Zeichen in ASCII-Code (dezimal) um.

a = C2D("A") ==> a == 65
  • C2X

C2X() wandelt Zeichen in ASCII-Code (hexadezimal) um

a = C2D("A") ==> a == 41
  • D2C

D2C() wandelt Dezimalzahlen in Zeichen um

a = D2C(33) ==> a == "!"
  • D2X

D2X() wandelt Dezimalzahlen in Hexadezimalzahlen um

a = D2X(255) ==> a == "FF"

Einleitung

Bearbeiten

Im Gegensatz zu anderen Programmiersprachen beginnen bei REXX alle Schleifen mit do. Die Gestaltung dieser do-Schleife kann sehr vielfältig sein.

Ein Block von Anweisungen

Bearbeiten

Wenn man eine feste Folge von Anweisungen braucht, dann lassen sie sich mit einer do-end Kombination gliedern:

Folge von Anweisungen:

do
 Anweisung1
 Anweisung2
 Anweisung3
  .
  .
  .
 AnweisungN
end


begrenzte Anzahl von Wiederholungen

Bearbeiten

Soll eine Schleife eine fest vorgegebene Anzahl durchlaufen werden, dann kann man hinter dem do einen Ausdruck angeben, der die Anzahl der Wiederholungen bestimmt (Beispiel):

do 5
 say "Hallo"
end

Es wird fünfmal "Hallo" ausgegeben

Zähl-Schleife

Bearbeiten
do index=start to ende by schrittweite
 Anweisung1
 Anweisung2
 Anweisung3
  .
  .
  .
 AnweisungN
end


While-Schleife

Bearbeiten
do while Bedingung
 Anweisung1
 Anweisung2
 Anweisung3
  .
  .
  .
 AnweisungN
end


Endlos Schleife (mit optionaler Abbruchbedingung)

Bearbeiten
do forever
  Anweisung1
  Anweisung2
  Anweisung3
   .
   .
   .
  AnweisungN
  if Abbruchbedingung then leave
end



Einleitung

Bearbeiten

Wie in den meisten Programmiersprachen kann man auch in REXX eigene Funktionen schreiben. Es lassen sich auch externe Bibliotheken erstellen. Egal ob es sich um eine eigene Funktion innerhalb des Programms handelt, oder um eine externe Bilbliothek, der Aufruf ist immer:

call funktionsname parameter

eigene Funktionen innerhalb des Programms

Bearbeiten

Als Beispiel ein Programm zur Ausgabe der Fakultät. Die eigentliche Berechnung der Fakultät findet in der selbst geschriebenen Funktion statt.

/* Ein Rexx-Programm */
do forever
  say "Bitte gib eine Zahl >= 0 ein"
  pull n
  call fakultaet n
  say "die Fakultaet zu" n "ist" result
end
/* */
FAKULTAET: procedure
  arg n
  if n = 0 then n = n + 1
  if n = 1 then n = n * 1
  if n > 1 then do
    call fakultaet (n - 1)
    n = n * result
  end
return n

Als Rückgabeparameter fungiert result.

Externe Bibliothek

Bearbeiten

Eine externe Bibliothek muß erst in das Programm dazu geladen werden. Das bewirkt die Anweisung:

call load 'datei'


/* Ein REXX-Programm */
call load 'convert.r'
do forever
  pull zahl
  pull base
  call d2n zahl,base
  say zahl'='result
end

Die externe Bibliothek ist nicht ablauffähig. Um auf diesen Umstand hinzuweisen, kann man der Bibliothek zwei Zeilen an den Anfang stellen:

say 'Only a Library!'
exit 1

Diese zwei Zeilen bewirken, das beim Starten der Bibliothek eine Meldung ausgegeben wird, das es sich bei der ausgeführten Datei um eine Bibliothek handelt. Das exit 1 beendet dann die Datei. Beim Aufruf mit call load aus einem REXX-Programm haben diese beiden Zeilen keine Auswirkungen.

/* REXX-Programm */
say 'Only a Library!'
exit 1
/* */
/* */
D2N: procedure
  arg n,b
/* initialisierung */
  z='0123456789ABCDEFGHIJKLMNOPQRSTUVW'
  conv =
  nstart = n
  DO WHILE n > 0
    p = n // b
    conv = substr(z,(p+1),1)||conv  
    n = n % b
  END 
/* Ausgabe der Konversion in der Form: 23 = (10111)2 */
return conv

Sieb des Erathostenes

Bearbeiten
/* Ein Rexx-Programm */
/* Initialisierung */
do index = 2 to 10000
  zahl.index = 1     /* Alle Zahlen sind Primzahlen */
end
/* Primzahlen sieben */ 
do index = 2 to 100
  if (zahl.index = 1) then do index2 = (index*index) to 10000 by index
      zahl.index2 = 0
  end
end
/* Ausgabe der Primzahlen */
do index = 2 to 10000
  if (zahl.index = 1) then say index
end
 

Primzahltest naiver Ansatz

Bearbeiten
/* Ein REXX-Programm */
initial=1
obergrenze = 10000
anzahl_primzahlen = 1
primzahl_zeiger.1=2
say 2
do index = 3 to obergrenze
  primzahl_wahr = 1
  laeufer = initial
  do anzahl_primzahlen
    laeufer = primzahl_zeiger.laeufer
    if (index // laeufer = 0) then primzahl_wahr = 0
  end
  if (primzahl_wahr = 1) then do 
    primzahl_zeiger.laeufer = index
    anzahl_primzahlen = anzahl_primzahlen + 1
    say index
  end
end

Übersicht der REXX-Anweisungen (unvollständig)

Bearbeiten
REXX-Anweisungen
address umgebung ausdruck zum Ausführen von Anweisungen außerhalb der REXX-Umgebung address DOS 'DIR *.*'
call prozedur Aufruf einer prozedur call binkoeff n k
call load 'bibliothek' Eine externe Bibliothek laden call load 'mathe.r'
clear löscht den Bildschirm
delete datei Löscht die Datei datei
do Alle möglichen Arten von Schleifen
drop variable variable löschen drop a
exit veranlasst das Programm sich zu beenden
if bedingung then anweisung Selektionsbefehl if a > 0 then a = a + 1
interpret ausdruck ausdruck wird wie eine REXX-Anweisung behandelt interpret "a=5*(4+b)"
iterate Leerdurchlauf einer Schleife ohne Ausführung der hier kodierten Befehle
leave Verlassen einer Schleife
nop Leeranweisung, die nichts macht
parse Analyse von Eingaben und Variablen (Vorlaufinformation)
pull variable liest eine Zeichenkette von der Tastatur ein pull eingabe
say ausdruck ausdruck wird auf dem Bildschirm ausgegeben say "Hallo Welt!"
signal label Äquivalent zu goto label

Übersicht der REXX-Funktionen (unvollständig)

Bearbeiten
REXX-Funktionen
address() gibt die Umgebung zurück z.B: address() == 'DOS'
arg(1) Enthält die Eingabe aus der Kommandozeile console = arg(1)
charin("dateiname") holt ein Zeichen aus dem Eingabestrom zeichen = charin("semmel.txt")
charout() schreibt ein Zeichen in den Ausgabestrom
chars() gibt die Anzahl der noch verfügbaren Zeichen im Eingabestrom aus
date() Funktion Datum gibt je nach Option Tages bzw. Datumsangaben zurück.
linein("dateiname") Liest eine ganze Zeile aus einer Datei ein zeile = linein("semmel.txt")
lineout("dateiname",ausdruck) ausdruck wird in Datei geschrieben lineout("semmel.txt",eumel)
lines() gibt die Anzahl der noch vollständigen Zeilen im Eingabestrom aus
Stringfunktionen
length(string) liefert die Länge eines Strings zurück
lower(string) wandelt alle Buchstaben eines Strings in Kleinbuchstaben um
substr(string,position,zeichenzahl) Ein Teilstring aus string
upper(string) wandelt alle Buchstaben eines Strings in Großbuchstaben um
word(string,wort) gibt das n.te Wort des String aus a = word("polyglotte Katze",2)
words(string) gibt die Anzahl der Wörter des Strings aus a = words("Hallo Leute")
mathematische Funktionen
abs(zahl) liefert den vorzeichenlosen Teil einer Zahl zurück
bitand() Bitweises UND
bitor() Bitweises ODER
bitxor() Bitweises XOR
random(u,o,s) liefert eine zufällige Zahl in den Grenzen von u und o zurück. u,o und s sind optional
C2D() Wandelt Zeichen in ASCII-Code (dezimal) um
C2X() Wandelt Zeichen in ASCII-Code (hexadezimal) um
D2C() Wandelt Dezimalzahlen in Zeichen um
D2X() Wandelt Dezimalzahlen in Hexadezimalzahlen um

Übersicht der REXX-Operatoren (unvollständig)

Bearbeiten

Vergleichsoperatoren

Bearbeiten

Rexx verfügt über zwei Klassen von Vergleichsoperatoren, die exakt (z. B. ==) oder numerisch (=) vergleichen. Im zweiten Fall werden zunächst etwaige Rand-Blanks entfernt, weil diese für die Interpretation als Zahl nicht von Bedeutung sind.

Rexx unterstützt eine große Zahl von Varianten, wobei allerdings „nicht“ nicht, wie in manchen Sprachen üblich, durch das Ausrufungszeichen, sondern durch das mathematische Zeichen für „nicht“ (¬), ersatzweise den Backslash ausgedrückt wird (das Ausrufungszeichen gehört zum Zeichenvorrat für Bezeichner!)

Vergleichs-Operatoren Beispiel Ergebnis
exakt gleich == "1" == 1 0
numerisch gleich = "1" = 1 1
nicht exakt gleich     ¬== \==
numerisch ungleich <>  ¬=  \=
exakt größer >> 30 >> "4 " 0
numerisch größer > 30 > "4 " 1
exakt größer oder gleich >== ¬<< \<<
numerisch größer oder gleich >=  ¬<  \<
exakt kleiner << 30 << "4 " 1
numerisch kleiner < 30 < "4 " 0
exakt kleiner oder gleich <== ¬>> \>>
numerisch kleiner oder gleich <=  ¬>  \>

sonstige Operatoren

Bearbeiten

Die Operatoren +, -, * und / werden nicht extra aufgeführt.

REXX-Operatoren
** Potenz 4**3 == 64
% ganzzahlige Division 11%3 == 3
// Rest-Operator (Modulo) 11//3 == 2
& logisches UND a & b => wahr, wenn a und b wahr sind
| logisches ODER a | b => wahr wenn a oder b wahr ist
&& logisches XOR a && b => wahr, wenn entweder a oder b wahr ist, aber nicht beide gleichzeitig
|| Stringverkettung (Konkatenation) "bär"||"tiger" = "bärtiger"

REXX-Versionen

Bearbeiten
  • BREXX - Vasilis Vlachoudis (DOS, Linux, Amiga, ...)
  • Regina (Linux, Windows, ...)
  • ARexx (Amiga)

Literatur

Bearbeiten
  • Michael Cowlishaw, The Rexx Language: A Practical Approach to Programming, ISBN 0137806515
  • Michael Metz et al., ARexx. Eine Einführung und mehr, ISBN 3930733005
  • Karlheinz Wittemann, REXX unter MVS-TSO/E, ISBN 3446179569
  • Howard Fosdick, Rexx Programmer's Reference (Wiley/Wrox: 2005), ISBN 0764579967
Bearbeiten