Dreifelderwirtschaft: Benutzung von Arrays, die Aditalk nicht kennt

Arrays sind indizierte Datenfelder. Aditalk kennt keine Arrays. Anwender müssen dennoch nicht darauf verzichten: TOS zeigt drei Methoden, diese Felder nachzubilden.

Indizierte Datenfelder bieten über Schlüsselnummern Zugriff auf jeden einzelnen Feldinhalt. Um diese Arrays in Aditalk nachzubilden, stehen drei Wege offen:

Betrachten wir zunächst die Strings. Die Aditalk-Dokumentation gibt die erlaubte Länge eines Strings mit 80 Zeichen an. Tatsächlich beträgt die maximale Länge eines solchen Strings jedoch 256 Zeichen. Addieren Sie hintereinander gleichlange Strings in einen neuen String, erhalten Sie ein Array, das sich leicht mit dem SUB-STR-Befehl abfragen läßt.

Sie wollen z. B. zehn Dateinamen in ein Array überführen. Das Directory befindet sich in einer Datei [dir.dat], die Sie vorher mit RUN angelegt haben. Bestimmen Sie jetzt einen Leerstring [dir] und lesen in ihn die einzelnen Zeilen von [dir.dat] so ein, daß jeder Dateiname genau zwölf Zeichen lang ist.

STORE "" TO dir 
SET INPUT TO "dir.dat”
SET CONSOLE OFF 
SET INPUT ON 
DO WHTLE(not eof)
	ACCEPT TO t
	STORE t+SPACE (12-LEN (t)) TO t 
	STORE dir+t TO dir 
ENDDO
SET INPUT OFF 
SET INPUT TO ""
SET CONSOLE ON

Verwenden Sie nun den SUBSTR-Befehl und eine einfache Zähl variable [i], um aus dem Array-String [dir] einzelne Dateinamen zu eliminieren.

STORE SUBSTR( dir, i*12+1, 12) TO dat 
STORE TRIM dat TO dat

In der Variablen [dat] befindet sich jetzt der i-te Name des Array-Strings [dir].

Eine weitere Anwendung für einen String als Array bietet sich, wenn Sie Suchergebnisse für später festhalten wollen. Nehmen wir an, daß Sie im Postleitzahlengebiet 8xxx alle Kunden suchen, deren Umsatz 3000 Mark übersteigt und die zur Branche X gehören. Die passenden Datensätze wollen Sie aber nicht sofort, sondern erst später weiterverarbeiten. Als Lösung bietet sich an, die SKIP-Abstände der passenden Datensätze in ein Stringarray zu speichern.

INDEX Plz
STORE "" TO wahl
STORE 0 TO x
STORE 1 TO n
STORE FIND 8000 TO ok
DO WHILE(Plz<=8999)
	IF(Branche="X" AND Umsatz>3000)
		STORE wahl+STR(X,2,0) TO wahl 
		STORE n+1 TO n 
		STORE 1 TO x 
	ELSE
		STORE x+1 TO x 
	ENDIF 
	SKIP +1 
ENDDO

Nach Beendigung der Suche stehen in »wahl« die einzelnen Blätter-SKIPs. Wo wir schon dabei sind, gleich noch etwas Komfort in die Bedienung: Wollen Sie mit den Pfeiltasten , blättern und mit «Return* die Ausgabe abbrechen, lautet die Routine folgendermaßen:

STORE 1 TO i
STORE FIND 8000 TO ok
SKIP INT(SUBSTR(wahl,i 2 1,2))
DISPLAY
DO WHILE(true)
	WAIT TO msg 
	DO CASE
		CASE(LASTKEY()="right" AND i<n)
			STORE i+1 TO i 
		CASE(LASTKEY()="left" AND i>1)
			STORE i-1 TO i 
		CASE (LASTKEY () ="cr")
			EXIT
		OTHERWISE
			BELL
	ENDCASE
	SKIP INT(SUBSTR(wahl,i*2-1,2))
	DISPLAY NONAMES 
ENDDO

Logische Datei als Array - Ersatz

Als Array läßt sich auch eine logische Datei (ein Karteikasten) verwenden, wenn Sie diese vorher mit INIT.PRG angelegt haben. Diese Variante bietet sich z. B. für Menüs an. Als Menü verstehe ich hier auch die Auswahl vorgegebener Textzeilen, etwa für Anreden, Konditionen usw. Die logische Datei heißt dann z. B. »TABU«. Als Schlüsselmerkmal bietet sich ein 1-bis 2-stelliges Nummernfeld an. Als Menü legen Sie ein Mehrfach-Stringfeld von entsprechender Zeichenlänge an. Nehmen wir an, daß das Menüfeld **m« heißt. Es soll acht Zeilen enthalten, die schon beschriftet sind. Das Menü geben Sie folgendermaßen aus:

STORE 1 TO i
STORE(JUMP 1 TO tabu.nr) TO ok 
DO WHILE(i<9)
	@ i+5,20 ?? m(i)
	STORE i+1 TO i 
ENDDO

Das Menü soll so reagieren, daß es die jeweils aktuelle Menüzeile invertiert anzeigt. Dazu ist es notwendig, dem Ausgabestring ein CHR(27)+'p' voranzustellen. Die Steuerung der Auswahl in den Menüeinträgen erfolgt durch die Pfeiltasten auf und ab. Ein auf in der ersten Zeile soll zur letzten springen, ein ab in der letzten wieder zur ersten Zeile. Return bestätigt den aktiven Menüpunkt. Die Sequenz zur Zeilenschwärzung weisen wir der Variablen [p] zu. Das Auswahllisting lautet:

STORE CHR(27)+'p' TO p
STORE 1 TO i 
DO WHILE(true)
	WAIT TO msg 
	DO CASE
		CASE(LASTKEY() ="down" AND i<8)
			STORE i+1 TO i 
		CASE(LASTKEY()="down" AND i=8)
			STORE 1 TO i 
		CASE(LASTKEY()="up" AND i> 1)
			STORE i-1 TO i 
		CASE(LASTKEY()="up" AND i=1)
			STORE 8 TO i 
		CASE (LASTKEY() ="cr")
			EXIT
		OTHERWISE
			BELL
	ENDCASE
ENDDO
BACK

Die getroffene Auswahl steht jetzt als Ziffer in [i] und läßt sich entsprechend weiterverarbeiten. Vergessen Sie nicht, mit BACK in die aktuelle Datei zurückzuspringen.

Benötigen Sie das Menü für das Auswählen einer Anrede oder Kondition, müssen die zugehörigen Textzeilen in entsprechender Länge angelegt und beschriftet sein. Ausgewählt wird mit der oben gezeigten Routine oder über Eingabe einer Zifferntaste. Für diesen Fall sollten Sie die Wahlpunkte mit der dazugehörigen Nummer als Info anzeigen. Im Ausgabelisting ändert sich dann die Zeile:

@ i+5,20 ?? m(i)

in die folgende Anweisung:

@ i+5,20 ?? STR(i,1,0)+" - "+m(i)

Das Auswahllisting verkürzt sich dabei wesentlich. Nehmen wir an, der Anwender soll eine von fünf Anreden auswählen, z. B.: 1-An, 2-Firma, 3-Herrn, 4-Frau, 5-Fräulein. Das Listing sieht folgendermaßen aus:

DO WHILE(true)
	WAIT TO msg
	STORE INT(msg) TO msg
	IF(msg>=1 AND msg<=5)
		EXIT
	ELSE
		BELL
	ENDIF
ENDDO

Mit [i] ist jetzt die ausgewählte Anrede aus dem Anredemenü an entsprechender Stelle einsetzbar. Vergessen Sie auch hier nicht den Rücksprung mit BACK.

Übersichtliche Listenausgabe

Ergibt eine Suche viele Datensätze, ist eine Listenausgabe übersichtlicher als die Anzeige einzelner Datensätze in der Maske. Der Bildschirm gibt aber je Zeile nur maximal 80 Zeichen aus. Abhilfe schafft ein horizontales Scrollen mit Tab und Backtab. Diese Hilfe ist leicht zu verwirklichen: Legen Sie gleichzeitig zur Bildschirmausgabe eine Datei an, in der je Datensatz in einer Zeile alle Feldinhalte nacheinander aufgelistet sind. Beim Horizontalscrollen lesen Sie diese Datei mit INPUT ein und bringen ihren Inhalt als SUB-STR auf den Bildschirm.

Bezeichnen wir die Fensterdatei als [datei.txt], die Seitenlange mit [z] und die Zeilenlänge mit [s]. Dabei ergibt sich [s] als Addition aller, jeweils um 1 erhöhten, Feldlängen.

s = LEN (Merkmal -1)+1 +
	LEN(Merkmal-2)+1 + 
	usw. +
	LEN(Merkmal-n)

Beginnt die Zeilenausgabe nicht in Spalte 0, müssen Sie zu [s] die führenden Leerspalten addieren. Fängt die Ausgabe nicht in Zeile 0 an, sind zu [z] die führenden Leerzeilen zu addieren. Achten Sie in diesem Fall auch darauf, solche Leerzeilen ebenfalls in die Fensterdatei einzufügen. Beim Lesen der Fensterdatei sind sie zu überspringen.

STORE 3 TO i
SET PRINTER TO "datei.txt,z,s"
SET PRINTER ON 
DO WHILE (i<z+1)
	@ i,2 ?? Merkmal-1,Merkmal-2, usw., Merkmal-n 
	> hier steht die Suchroutine, z.B. SKIP +1 <
	STORE i+1 TO i 
ENDDO
SET PRINTER OFF
SET PRINTER TO "prn:,72,80"

Die folgende Routine sorgt für ein Horizontalscrollen. Dabei entsprechen [x-1], [x-2] usw. der Spaltenanzahl bis Merkmal-1, Merkmal-2 usw., je Merkmal um 1 erhöht:

STORE 0 TO i
SET INPUT TO "datei.txt"
SET CONSOLE OFF 
SET INPUT ON 
DO WHILE(i<3)
	ACCEPT TO t 
	STORE i+1 TO i 
ENDDO
SET INPUT OFF 
SET CONSOLE ON

Durch die obigen Befehle werden die ersten drei Leerzeilen überlesen.

DO WHILE(i<18)
	SET CONSOLE OFF 
	SET INPUT ON
	ACCEPT TO t
	SET INPUT OFF
	SET CONSOLE ON
	@ i,2 ?? SUBSTR(t,x-? 2,76)
	STORE i+1 TO i 
ENDDO
SET INPUT TO ""

Die Pfeiltasten bewegen den Zeiger

Je nach x-? beginnt der ausgegebene 76 Zeichen lange String bei Merkmal-1 bis Merkmal-n. Beide Routinen müssen in einer Schleife eingebunden sein, wobei nach Ausgabe der ersten Seite eine Abfrage zum weiteren Vorgehen erforderlich ist: Scrollen oder nächste Seite ausgeben und in Fensterdatei speichern? Sind mehrere Seiten ausgegeben, müssen die vorhergehenden vor dem Horizontalscrollen überlesen werden. Das spielt aber zeitlich praktisch keine Rolle, weil ein sichtbarer Zeitaufwand nur für die Bildschirmausgabe vorhanden ist.

Um ausgegebene Datensätze auszuwählen, programmiert man einen Zeiger in Spalte 0, den die Pfeiltasten auf- oder abbewegen. Die Auswahl erfolgt mit Return. Nach Return enthält i die Zeilennummer, über die der Datensatz beim Einlesen der Fensterdatei manipulierbar ist.

STORE 3 TO i 
DO WHILE(true)
	@ 1,0 ?? ">"
	WAIT TO msg 
	DO CASE
		CASE(LASTKEY()="down" AND i<18)
			STORE i+1 TO i 
		CASE(LASTKEY()="up" AND i>3)
			STORE i-1 TO i 
		CASE (LASTKEY () ="cr ")
			EXIT
		OTHERWISE
		BELL
	ENDCASE
ENDDO

Die Einzelroutinen müssen in eine Schleife eingebunden sein. Wie sie aussehen, sehen sie auf der Diskette.

Um festzustellen, ob ein neues Fenster auszugeben ist, verwenden Sie z. B. eine Zählvariable »wi« sowie eine Kontrollvariable »wx« . Ähnliches gilt auch beim Horizontalscrollen für das Feststellen von [w-?]. (wk)


Hans Körner
Aus: TOS 07 / 1990, Seite 99

Links

Copyright-Bestimmungen: siehe Über diese Seite