H E B A S

Ein BASIC - Interpreter- Modulsystem
für 68HC11-, Z80-, HD64180-, Z280- und 80X86-Systeme
(für MS-DOS, CP/M und EURO-Z80)

Befehle und Erläuterungen der erweiterten Version
von Dr.rer.nat. Hehl Hans

(C) 1989-2010
Stand: 24.11.2010

Vorwort Start des Interpreters Basic-Warmstart und Kontrollzeichen Fehlermeldungen und Fehlerbehandlung
BASIC-BEFEHLE Dateistrukturen / Ein- und Ausgabe HEBAS und Mathematik Beispielprogramm

Vorwort:

Der BASIC-Interpreter HEBAS läuft je nach Version auf den verschiedensten Computern. So gibt es Versionen für CP/M 2.2, für CP/M-Plus, für den NDR-Rechner, für den mc-Computer, für MS-DOS und PC-DOS sowie für den EURO-Z80 oder 68HC11 der Fa. Kolter. Da keine illegalen Z80-Befehle verwendet werden, kann auch die CPU 64180 anstelle des Z80 eingesetzt werden. Auch unter CP/M-68k mit Z80-Emulator läuft HEBAS.

Welche Vorteile bietet dieser BASIC-Interpreter?

Was die Arbeit mit diesem Interpreter erheblich erleichtert, sind einerseits die deutschen Fehlermeldungen und andererseits die schon vorhandenen zahlreichen sog. TOOL-KIT-Befehle wie AUTO, FIND, REPLACE usw., die bei anderen bekannten Rechnertypen erst zusätzlich geladen werden müssen oder mittels EPROM zur Verfügung gestellt werden.

Als Besonderheit muß auch die Tatsache erwähnt werden, daß die Ein- und Ausgabekanäle beliebig definierbar sind, d.h. daß z.B. das Inhaltsverzeichnis der Diskette oder auch Pro-grammteile in eine Datei geschrieben werden können, die dann unter BASIC verändert wer-den kann. Für jede Version des Interpreters gibt es auch den Quellcode auf Diskette mit Kommentaren und Erklärungen. Eigene BASIC-Befehle lassen sich leicht einbauen.

Nachfolgend sind einige BASIC-Befehle aufgeführt, die bei anderen Basic-Interpretern nicht zur Verfügung stehen.

COPY Beliebiges Duplizieren von Programmteilen
DIR# Ausgabe in Dateien, damit bearbeitbar, Ausgabe auch auf Drucker
RESUME XY umfangreiche Fehlerbehandlung
EXCHANGE schneller Variablentausch (sortieren)
FIND Suchen von Zeichen bzw. Zeichenketten
HEX$ bzw. & Dezimal- u. Sedezimal-Umwandlung, damit direkte Eingabe von sedezimalen Zahlen
INPUT LINE Eingabe aller Zeichen (auch Komma!)
INSTR Suchen von Zeichen in Strings
MAT READ,MAT WRITE Matrix-Befehle
MID$ zusätzlich: Austausch von Stringteilen
KILL Löschung der Speicherreservierung (DIM)
LOADGO Laden und Starten eines Programmes
LOG, LOG10 Natürlicher u. dek. Logarithmus
LOOKUP Suchbefehl für Dateien im Directory
LVAR Ausgabe der Variableninhalte
MERGE Verbinden von Programmen
MOD Modulo-Funktion (Divisionsrest)
OPTION Veränderung der E/A-Kanal-Parameter
PI u. EE(Eulersche Zahl e) Werte gespeichert
PRECISION Arithmetik auf 11 Stellen
PRIVACY Schutz durch Passwort (alle Befehle)
REPLACE Ersetzen von Zeichen im Programm
RESTORE XY Datazeiger auf beliebige DATA-Zeile
RND,RANDOMIZE echte Zufallszahlen (aus Refresh)
SAVE,RESAVE Speicherung im ASCII-Format möglich, damit können Programme mit einem Texteditor bearbeitet werden.
TRACE Ausgabe der bearbeiteten Zeilennummern
USER Umschalten der USER-Bereiche (nur CP/M) von BASIC aus
USING Umfangreiche Formatierung (Zahlen,Texte)
VARPTR Adressenangabe der Stringzeiger

Im Handbuch werden Sedezimalzahlen ("Hexzahlen") durch ein nachgestelltes "h" gekennzeichnet, soweit in der Sedezimalzahl keine Buchstaben enthalten sind und eine Verwechslung mit Dezimalzahlen möglich ist. Basic-Befehle werden im Handbuch groß geschrieben (LOAD, SAVE), dürfen jedoch beliebig als Groß- oder Kleinbuchstaben eingegeben werden. Drücken der RETURN-Taste wird durch die Kurzfassung <CR> beschrieben, die Kontroll-Funktionen werden ähnlich abgekürzt, z.B. <CTRL-E>. Falsche Schreibweise der Befehle führt zur Meldung "Syntaxfehler".

Nachteile des Interpreters: Es gibt keinen bildschirmorientierten Editor (Terminal-System).

Aber: Schreiben Sie Ihr BASIC-Programm mit einem Textverarbeitungsprogramm im "Programmmodus" ohne Steuerzeichen. HEBAS kann ASCII-Texte lesen und so auch abspeichern (siehe SAVE).

 

Alphabetische Liste der BASIC-Befehle

Die nach einigen Befehlen angegebene Klammer soll darauf hinweisen, daß dem BASIC-Befehl ein Ausdruck in Klammern folgen muß (sonst Syntaxfehler).

ABS( INT( SGN(
AND INTERRUPT SIN(
ASC( KILL SPACE$(
ATN( LEFT$( SPC(
AUTO LEN( SQR(
BYE LET STEP
BYTE( LIST STOP
BYTE$( LOAD STR$(
BYTEPOLL( LOADGO STRING$(
CALL LOC( TAB(
CHR$( LOF( TAN(
CLEAR LOG( THEN
CLOSE LOG10( TO
CONT LOOKUP TRACE
COPY LVAR USER(
COS( MAT USING
DATA MERGE VAL(
DATE$ MID$( VARPTR(
DEF MOD WAIT
DELETE NEW WRITE
DIM NEXT XOR
DIR NOT ! PRINT USING
EDIT ON ^ EXPONENT
EE (2.7182818285) OPEN GANZZAHLDIVISION DIV
ELSE OPTION * MULTIPLIKATION
END OR + PLUS
EOF OUT - MINUS
EOF( OUTBYTE / DIVISION
EQV PEEK( ? PRINT
ERASE PI (3.1415926536) < KLEINER
ERL POKE = GLEICH
ERR POS( > GRÖSSER
ERR( PRECISION ' REM
ERROR PRINT  
EXCHANGE PRIVACY  
EXIT RANDOMIZE  
EXP( READ  
FIND READ(  
FIX$( REM  
FIX( RENAME  
FN RENUMBER  
FNEND REPLACE  
FNRETURN RESAVE  
FRE( RESET  
FOR RESTORE  
GOSUB RESUME  
GOTO RETURN  
HEX$( RIGHT$(  
IF RND  
IMP RND(  
INP( RUN  
INPUT SAVE  
INPUT LINE SETLOC  
INSTR(    

 

Fehlermeldungen:

1 NEXT ohne FOR 2 Syntaxfehler
3 RETURN ohne GOSUB 4 keine Daten
5 nicht erlaubt 6 Ergebnis zu gross
7 kein Speicherplatz 8 Sprungziel fehlt
9 DIM-Befehl falsch oder fehlt 10 DIM-Befehl doppelt
11 durch 0 teilen ? 12 kein Direktbefehl
13 Datentypen (Zahl/String) vermischt 14 kein Stringplatz
15 String zu lang 16 Ausdruck zu schwierig
17 CONT geht nicht 18 USER FN CALL fehlt
19 Dateiende falsch 20 Zeilen-Nr. falsch
21 BASIC verfügbar 22 FNRETURN ohne FN CALL
23 Zeilen-Nr. fehlt 24 RECORD zu lang
25 MATRIX nicht definiert 26 Kanal falsch
27 RESUME ohne ERROR 28 Inhaltsverzeichnis voll
29 Extension falsch 30 DISK voll
31 Datei nicht gefunden 32 Datei existiert
33 Datei geschlossen 34 OPEN-Modus falsch
35 Dateiname falsch 36 OPTION falsch
37 INPUT nicht offen 38 OUTPUT nicht offen
39 Wahlzugriff geht nicht 40 Datei nicht offen
41 keine Binäreinheit 42 kein Dateiplatz
43 RECORD-Nr. falsch 44 DISK geschützt
45 EXIT ohne FOR 46 nicht verfügbar
47 nicht vorhanden 48 kein internes Format
49 Fehler unbekannt  

Systemfehlermeldungen:

* Falsche Eingabe*
* Komma falsch *
** HALT **
** HALT ** Zeile ZE
nicht gefunden * Sprungziel fehlt *

 

Start des BASIC-Interpreters

Nach dem Laden und Starten des Basic-Interpreters wird nach der Speichergrenze ge-fragt. Eingabe von <CR> reserviert je nach Version verschieden großen Speicherplatz für Programme und zusätzlich 100 Bytes für Zeichenketten. Eingabe einer Dezimal- oder einer Sedezimalzahl (mit Kennzeichnung "&" als erstes Zeichen) begrenzt den Speicher, um z.B. ein Maschinenprogramm im oberen Speicherbereich zu schützen.

Beispiele (Werte je nach Version verschieden)
Eingabe: 45056 <CR> Anzeige: 26411 Bytes frei
&B000 <CR> 26411 " "
&DC07 <CR> 37672 " "

Bei der Eingabe von Sedezimalzahlen sind nur Großbuchstaben erlaubt. Bei falschen Eingaben und bei Zahlen größer 56327 kommt die Frage "Speichergrenze?" wieder und es kann eine neue Zahl eingegeben werden. Nach der Meldung des Interpreters wird bei der Diskettenversion nach dem Datum gefragt. Es können bis zu 20 beliebige Zeichen eingegeben werden, die mit PRINT DATE$ abrufbar sind, z.B. 31. Dezember 1991 **. Die Eingabe von <CR> ergibt die Meldung "Fertig" ohne aktuelles Datum.

a) Hinweise für CP/M-Plus beim NDR-Rechner:

Es stehen 42536 Bytes für BASIC-Programme zur Verfügung.

b) Hinweise für den NDR-Klein-Computer:

Beim Start wird automatisch der Bildschirm gelöscht und der deutsche Zeichensatz eingeschaltet. Wer dies nicht möchte oder verändern will, kann im Quellcode die Bytes 1A 1B 7A 31 abändern (1A = CTRL-Z: Bildschirm löschen, 1B = ESCAPE: Sonderfunktion, 7A 31 = z 1: deutscher Zeichensatz).

c) Hinweise für mc-Computer:

Durch den mc-Monitor sind beim Start folgende IOBYTE-Belegungen vorgegeben: C=T, R=T, P=T, L=T. Ist ein Drucker am System angeschlossen, so muß vor dem CP/M-Start "AL=L" eingegeben werden.

d) EURO-Z80 Eprom-Interpreter von Elektor

Der Interpreter im Eprom wird über die V24-Schnittstelle mittels Terminalprogramm vom PC aus gesteuert. Als Terminalprogramm eignet sich z.B. Procomm aus dem Shareware-Bereich. Diese Eprom-Version enthält natürlich keine Diskettenbefehle. Es fehlen zusätzlich auch noch einige Befehle, da der Platz im Eprom nicht ausreicht.

e) EURO86-Interpreter: MS-DOS-Version des EURO-Z80

Diese Version ist identisch zur EURO-Z80-Version, d.h. es liegen die gleichen Adressen-lagen von Programm und Variablen vor. Die Befehle DIR, LOAD, SAVE, RESAVE und RESET(Laufwerk) sind in dieser Version vorhanden. So kann ein Basic-Programm dann direkt in ein Eprom abgelegt werden.

f) HEBAS86-Interpreter: Vollversion mit allen Befehlen

Hier liegt die Vollversion vor, die identisch zum Z80-CP/M-Interpreter ist.

Basic-Warmstart

a) mc-Computer und CP/M 2.X

Wird während des Betriebes die RESET-Taste (auch BREAK-Taste genannt) betätigt, so wird aus dem Eprom der Monitor neu geladen, ohne daß der Speicher gelöscht wird. Arbeitet man nur mit dem Laufwerk A weiter, genügt die Eingabe "g100" und der BASIC-Inter-preter antwortet mit der Meldung "BASIC verfügbar". Wurde z.B. in einer Endlosschleife mit der RESET-Taste abgebrochen, erfolgt nach dem Warmstart die Meldung "BASIC verfügbar Zeile XYZ".

Will man nachträglich das IOBYTE verändern, so kann dies auf zweierlei Art geschehen. Mittels RESET-Taste wird der Monitor gestartet. Nun kann eine andere Zuordnung getroffen und ein BASIC-Warmstart durchgeführt werden. Man kann aber auch mittels POKE-Befehl den Dezimalwert des IOBYTE in die Speicherstelle 61697 (F101h) schreiben (POKE &F101, Dezimalwert). Der Dezimalwert 128 gilt für die Einstellung AL=L, 0 für AL=T (siehe IOBYTE-Tabelle).

b) NDR-Klein-Rechner und mc-Computer mit CP/M 2.X

Will man nach dem Warmstart mit Laufwerk B arbeiten, muß nach dem Monitor-Start zu-erst CP/M geladen werden. Danach wird durch Aufruf eines Pseudoprogrammes CONT.COM auf Adresse 100h gesprungen und der Interpreter gestartet. Das Programm CONT.COM enthält keine Bytes und wird einfach mit dem CP/M-Befehl "SAVE 0 CONT.COM" gespeichert. Laden oder Abspeichern von Programmen mit dem Befehl LOAD oder SAVE ergibt die Fehlermeldung "kein Dateiplatz". Der Befehl CLEAR,0 (Komma eingeben!) reserviert für diese Vorgänge wieder Speicherplatz und Laden oder Abspeichern von BASIC-Programmen funktionieren wieder.

Tritt beim Betrieb des BASIC-Interpreters z.B ein BDOS ERR ON A: R/O auf, meldet sich nach Eingabe von <CTRL-C> CP/M mit dem Laufwerkbuchstaben, z.B. "A>". Durch Eingabe von CONT (Meldung: BASIC verfügbar) und CLEAR,0 kann mit dem BASIC-Interpreter weiter gearbeitet werden, ohne daß ein Programmverlust eingetreten ist. Das mit DATE$ abrufbare aktuelle Datum bleibt beim Warmstart erhalten.

c) NDR-Klein-Rechner und CP/M-Plus

CP/M-Plus überschreibt beim Kalt- und Warmstart den TPA -Bereich in Bank 1 ab 100h mit dem CCP. Damit werden wichtige Flag-Tabellen des Basic-Interpreters zerstört.

Kontrollzeichen:

<CTRL-E>:
Die Ausführung eines BASIC-Programmes oder eines Direktbefehles wird abgebrochen und die Meldungen "^E","** HALT ** Zeile XYZ" oder nur "** HALT **" und dann "Fertig" ausgegeben.
Die Abbruchmöglichkeit mit <CTRL-E> wird mit dem Befehl INTERRUPT X in einem BASIC-Programm abgeschaltet, wobei zuvor mit X = 0 der Variablen X der Wert 0 zuge-wiesen oder gleich INTERRUPT 0 vorgesehen wird. Der Ausstieg aus der Schleife in einer Programmzeile "15 goto 15" ist nur noch durch Neustart des Monitors (RESET-Taste) möglich. Allerdings wird die <CTRL-E>-Funktion durch Befehle wie INPUT im Programm wieder eingeschaltet, ebenso durch INTERRUPT 1.
Beim Befehl LIST unterbricht das Drücken der Leertaste die Ausgabe, ein erneutes Drücken setzt die Ausgabe fort. Wer dies rückgängig machen möchte, kann im Quellcode dies ändern.

<CTRL-U>:
Eine Eingabe im Programm oder als Direktbefehl wird gelöscht, solange nicht <CR> eingegeben worden war.

<CTRL-O>:
Die Ausgabe auf den Bildschirm wird im Programm oder bei einem Direktbefehl bis zur Mel-dung "Fertig" unterdrückt, aber nicht gestoppt. Der INPUT-Befehl bricht <CTRL-O> ab.

<CTRL-R>: nur bei CP/M
Es werden alle durch die Taste <DELETE> (Rubout) eingefügten Trennzeichen (') und die als "Echo" angezeigten zu löschenden Zeichen entfernt und die bereinigte Zeile neu ausgegeben. Der Cursor steht am Ende dieser Zeile und es kann mit der Eingabe fortgefahren werden.

<CTRL-Z>:
Es wird die Meldung "Dateiende falsch" ausgegeben. Dieser Befehl beendet z.B. auch eine Eingabe von der Tastatur über den READER-Kanal mit LOAD#3 (Strichcodeleser).

<CTRL-T>:
Wird während eines Programmablaufes die Tastenkombination <CTRL-T> gedrückt, so wird am Bildschirm die Zeilennummer ausgegeben, die gerade bearbeitet wird.

 

Dateistrukturen, Schreiben/Lesen und sonstige Ein- und Ausgabefunktionen

Moderne Textverarbeitungssysteme erübrigen oft umständliche Eingabe- und Ausgaberoutinen in BASIC. Eine Adressendatei z.B. läßt sich mit einem Textprogramm leicht anlegen, verändern und drucken. Aber schon ein Sortiervorgang oder eine spezielle Dateiart erfordern eine Bearbeitung mit einem eigens dafür entworfenen Programm. Der BASIC-Interpre-ter HEBAS bietet hierfür umfangreiche Befehle.

A) OPEN:

Befehlsform: OPEN # Kanal,"Modus","Laufwerk:Dateiname.Dateizusatz",Satzlänge

1) # Kanal: Für die Zusammenarbeit des Computers mit Peripheriegeräten werden Verbindungskanäle benötigt. Diese werden mit Nummern von 0 bis 255 gekennzeichnet.

Tabelle der Kanalnummern:

Konsole 0
Laden und Speichern von Programmn 1
Drucker (List-Device) 2
Leser (Reader) 3 (nur mc-Computer)
Stanzer (Punch) 4 (nur mc-Computer)
für spätere Erweiterungen 5-9
Floppy 10-255

Prinzipiell können alle Ein- bzw. Ausgabefunktionen über irgendeinen sinnvollen Kanal ablaufen. Eine Ausgabe von Zeichen auf die Konsole ist natürlich ebenso sinnlos wie die Ausgabe an die Leser-Schnittstelle. Laden und Speichern von Programmen kann nur über Kanal 1 ablaufen. Einem nicht angegebenen Kanal wird die Nummer 0 zugewiesen. Folgt einer Kanalzuweisung ein weiteres Argument, muß dies durch ein Komma von der Kanalnummer abgetrennt sein. Schließen eines nicht offenen Kanals bewirkt die Fehlermeldung "Datei nicht offen".

Kanalmerkmale: Die Voreinstellungen der Kanalparameter sind beim Befehl OPTION erläutert. Beim mc-Computer muß die IOBYTE-Einstellung L = L nach dem Start des Monitors vorliegen.

a) Kanal #0

Dieser Kanal ist immer offen. Der Befehl OPEN#0,"O" <CR> löscht den Bildschirm. Ausserdem werden die mit dem Befehl OPTION veränderten Voreinstellungen rückgängig ge-macht. Der Befehl CLOSE#0 <CR> löcht ebenfalls den Bildschirm und der Kanal bleibt offen.

b) Kanal #1

Laden oder Speichern von Programmen läuft über diesen fest eingestellten Kanal ab, was nicht verändert werden kann. Eine Kanalangabe wird beim LOAD- und SAVE-Befehl nicht berücksichtigt, bei RESAVE wird "Syntaxfehler" ausgegeben.

c) Kanal #2

Der Kanal zum Drucker ist immer offen. Der Befehl OPEN#2,"O" <CR> gibt ein Formfeed aus; die Kanalparameter (falls mit dem Befehl OPTION verändert) werden zurückgestellt. CLOSE#2 gibt ein Formfeed aus, der Kanal bleibt offen. FORMFEED = Seitenvorschub!

d) nur mc-Computer: Kanal #3

Der Reader-Kanal ist immer offen. Der Befehl OPEN#3,"I" <CR> stellt die Kanalparameter zurück. CLOSE#3 hat keine Auswirkung. Mit dem Befehl INPUT#3,A$ kann z.B. über die Tastatur ein Wort eingegeben werden, ohne daß die Zeichen auf dem Bildschirm erschei-nen.

e) nur mc-Computer: Kanal #4

Der Punch-Kanal ist immmer offen. Der Befehl OPEN#4,"O" gibt 16 Bytes mit dem Wert 255 (FF) aus und stellt die Kanalparameter zurück. CLOSE#4 gibt ein CTRL-Z (1A) aus, ge-folgt von 16 Bytes FF; der Kanal bleibt offen.

f) Die Kanäle 5 - 9 sollten nicht verwendet werden.

g) Kanäle 10 - 255

Für Diskettenlaufwerke sind die Kanäle 10 bis 255 verwendbar. Jeder Ausgabekanal wird mit einer eigenen Datei verbunden, deren Name im OPEN-Befehl angegeben wird. Die ma-ximale Anzahl der durch ein Programm gleichzeitig geöffneten Kanäle wird durch den CLEAR-Befehl bestimmt (siehe dort).

2) Modus:

Für die Verbindungskanäle zwischen Computer und Diskettenlaufwerk gibt es verschiedene Ausführungsarten, die durch die Großbuchstaben I, O, U und R abgekürzt, in Anführ-ungszeichen gesetzt und mit Kommas von anderen Argumenten abgegrenzt werden müs-sen. Der Modus kann auch durch eine Stringvariable angegeben werden (ansonsten Fehlermeldung "OPEN-Modus falsch").

a) I = Eingabe-Modus (Lese-Modus)

Diese Datei-Eröffnungsart wird für sequentielle Lesevorgänge von der Diskette benötigt. Die mit dem Dateinamen angegebene Datei wird auf der Diskette im angemeldeten oder eigens bezeichnetem Laufwerk gesucht und die Kanalverbindung hergestellt. Fehlt die Datei, erfolgt Fehlermeldung "Datei nicht gefunden". Der CLOSE-Befehl für einen solchen Kanal hat keine Funktion.

b) O = Ausgabe-Modus (Schreib-Modus)

Sequentielle Schreibvorgänge erfordern diesen Modus. Die angegebene Datei wird wie beim I-Modus gesucht. Ist sie vorhanden, erfolgt die Fehlermeldung "Datei existiert Zeile XY", wenn nicht vorhanden, wird die Kanalverbindung hergestellt. Ein CLOSE nach einem solchen OPEN-Modus bewirkt die Ausgabe von CTRL-Z (1A), Leerung aller Zwischenspeicher und die Aktualisierung des Disketteninhaltsverzeichnisses.

c) U = Ergänzungsmodus (Lese- und Schreibmodus)

Lesen und Schreiben sind über einen Kanal möglich. Bei diesem Modus wird bei nicht gefundener Datei die Fehlermeldung "Datei nicht gefunden Zeile XY" angezeigt, ansonsten die Verbindung hergestellt. Jeder Schreibvorgang beginnt an der gleichen Stelle wie der vorhergehende Lesevorgang, jeder folgende Lesevorgang beginnt mit dem ersten, noch nicht bearbeitetem Byte. CLOSE ergibt eine Leerung der Zwischenspeicher und die Aktualisierung des Inhaltsverzeichnisses.

d) R = Random-Modus (Lese- und Schreibmodus, wahlfrei)

Hier kann sowohl sequentiell als auch mit wahlfreiem Zugriff geschrieben oder gelesen werden. Fehlt die angegebene Datei, wird sie neu angelegt. Ist sie vorhanden, wird sie ergänzt oder an den bezeichneten Stellen überschrieben (wahlfreier Zugriff), ohne daß Fehlermeldungen wie bei den anderen Zugriffsarten erfolgen. CLOSE leert die Zwischenspeicher und aktualisiert das Verzeichnis.

Allgemein:

Ein OPEN-Befehl setzt den Byte-Zeiger der Datei auf das erste Byte des Dateiinhaltes. Dies kann ohne Fehlermeldung bei der gleichen Datei beliebig oft wiederholt werden.

Ein CLOSE-Befehl schließt die Bearbeitung der Datei ab und trennt die Verbindung zur Datei. Mit dem CLEAR-Befehl reservierter Speicherplatz bleibt reserviert.

3) Laufwerk:Dateiname.Dateizusatz

Fehlt die Laufwerksangabe, wird die Datei auf der Diskette in dem angemeldetem Laufwerk gesucht. Sternchen im Dateinamen können bei Schreibvorgängen nicht als Abkürzung verwendet werden (Auffüllung mit Fragezeichen). Fehlt der Dateizusatz, wird er durch .BAS ergänzt. Die drei Parameter dürfen auch durch Variableninhalte bestimmt werden.

4) Satzlänge:

Diese Zahl bestimmt die Länge eines einzelnen Datensatzes und muß als Ganzzahl im Bereich von 1 bis 32767 eingegeben werden. Beim R-Modus wird sie sonst gleich 1 gesetzt, bei den anderen Modus-Arten bleibt sie unberücksichtigt.

Um auf beliebige Teile einer Datei zugreifen zu können, ohne daß die ganze Datei in den Kernspeicher geladen wird, benötigt man die Adresse des Anfangsbytes des gesuchten Dateiteiles. Diese wird intern durch Multiplikation einer Satznummer (1 - 4194303) mit der Satzlänge errechnet. Da jedoch die Satzlänge auch die Trennzeichen (es sind dies die Bytes 22h, 0A und 0D) der Dateisätze beinhaltet (siehe OPTION), muß zur eigentlichen Datensatzlänge noch der Wert 4 dazu addiert werden, sonst wird nicht auf den Anfang der Datensätze zugegriffen. Die gesamte Dateilänge (Summe der Satzlängen) kann unberücksichtigt bleiben oder man beschreibt beim Anlegen der Datei alle Datensätze mit einem Leerstring.

B) Schreib- und Lesevorgänge:

Für Schreib- bzw. Lesevorgänge werden zunächst nur noch folgende Befehle benötigt.

a) Schreiben: PRINT: Befehlsform: PRINT # Kanal @ Satznummer, Variable 1, Variable 2, usw.

Die Satznummer wird durch den vorangestellten Klammeraffen "@" gekennzeichnet, beide werden nur für Schreibvorgänge bei wahlfreiem Zugriff benötigt. Nummerische Variablen Zahlen), Textvariablen und Ausdrücke sind erlaubt.

b) Lesen: Input: Befehlsform: INPUT # Kanal @ Satznummer, Variable 1, Variable 2, usw.

Bis zu 250 Zeichen können über den angegebenen Kanal eingelesen werden (sonst Fehlermeldung "Record zu lang Zeile XY"). Um auch Kommas einlesen zu können, bedarf es des Befehles INPUT LINE # Kanal ... . Die mit dem Befehl OPTION angegebenen Trennzeichen werden mitgelesen, ausgenommen die ASCII-Zeichen 32h, 34h und 27h.

Es folgen nun Beispiele zur sequentiellen sowie zur wahlfreien Dateibearbeitung.

1) sequentiell schreiben

5 CLEAR 250
10 OPEN#15,"O","A:TEST.DAT"
20 INPUT A$:PRINT#15,A$
30 CLOSE#15

Es wird die Datei TEST.DAT über den Kanal Nr. 15 erstmalig im Ausgabe-Modus eröffnet (Fehlermeldung, wenn die Datei TEST.DAT schon im Inhaltsverzeichnis der Diskette steht, siehe auch den Befehl LOOKUP im Abschnitt C). Nach der Eingabe bis zu 250 Zeichen ohne Kommas in die Variable A$ wird diese über den Kanal Nr. 15 ausgegeben, auf die Diskette im Laufwerk A geschrieben und mit CLOSE#15 die Bearbeitung abgeschlossen.

Wurde z.B. die Zeichenkette AAA* eingegeben, so werden beim Schreibvorgang folgende Zeichen (sedezimal) auf Diskette geschrieben:

22 41 41 41 2A 22 0D 0A 00 00 00 00 00 usw., auf 128 Bytes mit Nullen aufgefüllt.

Mehrere Eingaben können auch über eine FOR-NEXT-Schleife mit indizierten Variablen, z.B. A$(I), durchgeführt werden.

2) sequentiell lesen

5 CLEAR 250
10 OPEN#15,"I","TEST.DAT"
15 ON EOF GOTO 30
20 INPUT#15,A$:PRINT A$
30 CLOSE#15
40 END

Die in der Datei TEST.DAT enthaltene Zeichenkette wird in die Variable A$ über den Kanal Nr. 15 eingelesen und auf den Bildschirm ausgegeben. In Zeile 20 beider Beispiele können, durch ein Komma getrennt, auch mehrere Variablen stehen:

a) Schreiben: 20 INPUT A$,B$,C$,D$:PRINT#15,A$,B$,C$,D$

b) Lesen: 20 INPUT#15, A$,B$,C$,D$:PRINT A$,B$,C$,D$

3) sequentiell lesen und schreiben

5 CLEAR 250
10 OPEN#25,"U","TEST.DAT"
20 INPUT#25,A$:PRINT A$
30 INPUT"RICHTIG";X$
40 : IF X$ ="NEIN" THEN INPUT A$
50 PRINT#25,A$:GOTO 20
60 END

Aus einer bestehenden Datei wird jeweils eine Zeichenkette gelesen und falls für richtig befunden, wieder auf Diskette geschrieben. Nach dem Lesen der letzten Zeichenkette der Datei ergibt ein weiterer Lesezugriff die Fehlermeldung "Dateiende falsch Zeile 20". Dies kann durch eine Programmzeile 25 ON EOF GOTO 60 abgefangen werden.

4) wahlfrei schreiben

5 CLEAR 250
10 OPEN#10,"R","TEST.REC",104
20 FOR I = 1 TO 5
30 INPUT A$(I):PRINT#10@I,A$(I)
40 NEXT:CLOSE#10

Es werden 5 Datensätze mit einer Länge von 100 Zeichen in der Datei TEST.REC abgelegt.

5) wahlfrei lesen

5 CLEAR 250
10 OPEN#250,"R","TEST.REC",104
20 INPUT"Satznummer";SN: IF SN = 0 THEN END
30 INPUT#250@SN,A$:PRINT A$: GOTO 20
40 CLOSE#250

Jeder der mit Beispiel Nr.4 eingebenen fünf Datensätze kann beliebig gelesen werden. Hier zeigt sich die Grenze solcher einfacher Beispiele. Eine falsche Datennummer SN ergibt falsche Zeichenketten oder die Fehlermeldung "Dateiende falsch Zeile XY". Dies muß durch das Programm abgefangen werden. Beachten Sie dazu das Beispielprogramm mit Erläuterung am Schluß des Handbuches.

C) Weitere Befehle zur Dateiverarbeitung:

1) BYTE(: Befehlsform: BYTE (# Kanal)

Damit können über den angegebenen Kanal sequentiell die dezimalen Werte der Bytes einzeln gelesen werden. Das Nummernzeichen "#" kann entfallen. Beispiel:

5 CLEAR 250
10 OPEN#15,"I","A:TEST.DAT"
20 B = BYTE(#15):PRINT B;
30 ON EOF GOTO 100
40 GOTO 20
50 :
100 CLOSE#15:PRINT"ENDE"

Es erfolgt die Ausgabe der Datei TEST.DAT zeichenweise in dezimalen Werten, z.B. der Datensatz "AAA" ergibt die Zeichenfolge 34 65 65 65 34 13 10 0 0 0 0 0 0 0 usw. bis 128 Bytes gelesen wurden.

Mit einer Programmzeile B = BYTE(#0) ist eine Tastaturabfrage möglich. Der Interpreter hält mit der Programmausführung an, bis eine Taste gedrückt wurde. Die Variable B enthält den dezimalen Wert der Taste, das Zeichen erscheint nicht auf dem Bildschirm.

10 PRINT"TASTE DRÜCKEN:";
20 B = BYTE(#0)
30 PRINT"ZEICHEN DEZ.:";B
40 : IF B = 5 THEN STOP ELSE GOTO 20

Da auch Steuerzeichen wie <CTRL-E> als dezimaler Wert (5) ausgegeben werden, muß zum Programmabbruch die Zeile 40 vorhanden sein. Weiterhin ist die Verwendung des Befehles auch in Verbindung mit dem Zusatz ON möglich:

10 ON BYTE(#0) GOTO 100,200
20 STOP
100 PRINT"1. Sprung"
110 STOP
200 PRINT"2. Sprung"

Bei Eingabe von <CTRL-A> erfolgt ein Sprung zur Zeile 100, bei <CTRL-B> ein Sprung nach 200, da die beiden Eingaben die dezimalen Werte 1 und 2 besitzen.

2) BYTE$( Befehlsform: BYTE$( # Kanal , Zeichenanzahl)

Damit kann jetzt ein ganze Zeichenkette auf einmal eingelesen werden. Das Nummernzeichen "#" kann entfallen. Die Trennzeichen (" oder mit OPTION verändert) der Zeichenkette werden mitgelesen und angezeigt. Eine fehlende Zeichenanzahl wird durch die Zahl 1 ersetzt.

5 CLEAR 250
10 OPEN#10,"I","A:TEST.DAT"
20 B$ = BYTE$(#10):PRINT B$;
30 ON EOF GOTO 100
40 GOTO 20
50 :100 CLOSE#10:PRINT"ENDE"

Die mit dem Beispiel Nr.1, Abschnitt B) geschriebene Datei wird gelesen und beim Zeichen CTRL-Z (1A) zur Zeile 100 gesprungen. Der Befehl BYTE$(#0,1) vereinfacht Eingaberoutinen, die nur bestimmte Zeichen als Eingabe zulassen.

10 PRINT"Bitte die Taste <F> drücken"
20 B$ = BYTE$(#0,1): IF B$ <> "f" THEN 20
30 PRINT"Fertig"

3) OUTBYTE: Befehlsform: OUTBYTE # Kanal @ Satznummer, Zahl oder Variable oder Zeichenkette

Es sind Zahlen von 0 bis 255 erlaubt. Von einer Zeichenkette wird jedes Zeichen als einzelnes Byte ausgegeben. Die Länge der Zeichenkette wird nicht wie beim WRITE-Befehl angegeben. Steuerzeichen wie CTRL-I und andere lassen sich so an Daten anhängen.

PRINT#12,A$;:OUTBYTE#12,9:PRINT#21,B$;:OUTBYTE#12,9

Diese Befehle fügen beim Schreibvorgang in eine Datei an A$ und B$ die Zeichen CTRL-I und 9 an. Weiterhin lassen sich mit OUTBYTE#0 Zahlenkolonnen ohne Zwischenraum ausgeben wie es bei dem Befehl PRINT nicht der Fall ist.

5 A = 1
10 FOR I = 1 TO 10
20 PRINT A; Ausgabe: 1 1 1 1 1 1 1 1 1 1
30 NEXT

dagegen:

5 A = 49
10 FOR I = 1 TO 10
20 OUTBYTE#0,A Ausgabe: 1111111111
30 NEXT

4) LOC(: Befehlsform: LOC( # Kanal )

Der Befehl gibt nach einem Schreib- oder Lesebefehl die Stellung des Byte-Zeigers an, d.h. die Zahl der insgesamt übertragenen Bytes einer Zeichenkette einschließlich Trennzeichen. Wurde z. B. mit dem Programm Nr.1 im Abschnitt B) eine Zeichenkette mit 10 Zeichen auf Diskette geschrieben, so gibt der Befehl PRINT LOC(#15) als Zeile Nr. 25 die Zahl 14 aus. Diese Zahl ist um 4 größer als die Länge der Zeichenkette (siehe auch Abschnitt A), Satzlänge). Das Nummernzeichen "#" kann entfallen. Wurde z.B. mit dem Befehl OPTION #10,"Q",0 das Trennzeichen zwischen einzelnen Datensätzen abgeschafft, so ist diese Zahl nur um 2 größer.

5) SETLOC: Befehlsform: SETLOC # Kanal @ Bytenummer, # Kanal @ Bytenummer, usw.

Dies ist das Gegenstück zum LOC(-Befehl. Es wird die Stelle in einem Datensatz angegeben, ab der ein Zugriff erfolgen soll. So kann bei sonst sequentieller Dateiverarbeitung in einem Datensatz wahlfrei gelesen oder geschrieben werden.

SETLOC#15@5 bedingt einen Zugriff ab dem fünften Byte des Datensatzes, setzt also den Byte-Zeiger auf das 5.Byte des Datensatzes der mit Kanal Nr. 15 eröffneten Datei. Man erspart sich so umständliche Stringoperationen bei sequentiellen Dateien.

10 OPEN#10,"I","A:TEST.DAT"
20 ON EOF GOTO 70
30 INPUT"Byte-Nummer";BN
40 SETLOC#10@BN
50 PRINT BYTE$(#10,2)
60 GOTO 30
70 END

Ab dem angegebenen Byte werden zwei Zeichen gelesen und angezeigt (siehe BYTE-Befehl).

6) LOF(: Befehlsform: LOF( # Kanal )

Es wird die von einer Datei auf einer Diskette belegte Byteanzahl (immer Vielfache von 128) ausgegeben, wobei zuvor diese Datei über einen Kanal eröffnet werden muß.

10 INPUT "Dateiname";A$
15 IF A$="e" THEN END
20 OPEN#10,"I",A$
30 PRINT LOF(#10)
40 GOTO 10

7) LOOKUP(: Befehlsform: LOOKUP("Laufwerk: DATEINAME.DATEIZUSATZ") oder LOOKUP(Stringvariable)

Wird mit dem O-Modus eine Datei eröffnet, so wird die Fehlermeldung "Datei existiert Zeile XY" ausgegebenen, falls eine Datei mit gleichem Namen schon vorhanden ist. Mit LOOKUP( kann dies abgefragt und mit dem ERASE-Befehl die Datei gelöscht werden. Der Befehl liefert den Wert -1, wenn die Datei vorhanden bzw. 0, wenn sie nicht vorhanden ist. Der Ausdruck in Klammern kann auch durch Variablen angegeben werden.

So kann beim Beispiel Nr.1 BYTE, Abschnitt B) die Zeile Nr. 7 eingefügt werden.

7 IF LOOKUP("A:TEST.DAT") THEN ERASE "A:TEST.DAT"

Der Dateiname kann auch in einer Variablen enthalten sein, er muß groß geschrieben sein.

IF NOT LOOKUP(LW$+":"+D1$) THEN .........

8) WRITE: Befehlsform: WRITE # Kanal @ Satznummer , Variable oder "Zeichenkette"

Dieser Befehl kann nur für binäre Ausgabeeinheiten verwendet werden (Kanal Nr.0 und Nr.2 ergeben die Fehlermeldung "keine Binäreinheit). Die Länge der in der Variablen enthaltenen Zeichenkette wird als erstes Byte vor den Zeichen der Zeichenkette auf Diskette geschrieben. Bei den im Abschnitt B) angegebenen Beispielen Nr.1 und 4 kann der Befehl PRINT # Kanal durch WRITE # Kanal ersetzt werden.

nur CP/M und mc-Computer:
Der Befehl WRITE #4 ohne weitere Argumente dient zur Ausgabe einer aus acht Bytes bestehenden Zeichenkette (FF FF FF FF FF FF FF 00), die als "data header" beim Kanal Nr. 4 verwendet wird, der vorher mit OPEN#4,"O" eröffnet werden muß (sonst Fehlermeldung "OUTPUT nicht offen").

9) READ: Befehlsform: READ # Kanal @ Satznummer , Variable

Nur von binären Eingabeeinheiten (nicht die Tastatur) kann mit diesem Befehl gelesen werden (sonst Fehlermeldung "keine Binäreinheit). Es werden soviele Zeichen eingelesen wie im ersten Byte der Zeichenkette angegeben sind.

nur mc-Computer:
READ #3 ohne Argumente liest solange Zeichen, bis ein "data header" gefunden wurde.

10) MAT WRITE: Befehlsform: MAT WRITE # Kanal @ Satznummer , Matrix 1, Matrix 2, usw.

Mit dem Befehl können ohne großen Programmieraufwand ein- oder zweidimensionale nummerische Matritzen über den angegebenen Kanal ausgegeben werden (nur Binäreinheiten).

5 DIM A(3,5)
10 FOR I = 1 TO 3
20 FOR J = 1 TO 5
30 INPUT A(I,J)
40 NEXT J,I
50 :
60 OPEN#10,"O","A:TEST.MAT"
70 MAT WRITE#10,A
80 CLOSE#10

Nach der Eingabe beliebiger Zahlen wird die Matrix ohne FOR-NEXT-Befehle direkt über Kanal Nr. 10 in die Datei TEST.MAT geschrieben.

11) MAT READ: Befehlsform: MAT READ # Kanal @ Satznummer , Matrix 1, Matrix 2 usw.

Die mit obigem Beispiel erstellte Matrix wird mit diesem Befehl wieder gelesen.

10 DIM A(3,5)
20 OPEN#10,"I","A:TEST.MAT"
30 MAT READ#10,A
40 CLOSE#10
50 REM Anzeige der Matrix
60 FOR I = 1 TO 3
70 FOR J = 1 TO 5
80 PRINT A(I,J);
80 NEXT J :PRINT: NEXT I

Zum Einlesen der Matrix muß diese vorher dimensioniert werden. Eine Dimensionierung, die von der beim Schreibvorgang vorhandenen abweicht, ergibt Lesefehler.

---------------

Fehlerbehandlung:

1) ERROR: Befehlsform: ERROR (Fehlernummer)

Wie schon im Abschnitt III bei den Direktbefehlen erläutert, kann mit dem Befehl ERROR XY (0-48) die Fehlermeldung XY ausgegeben werden. Fehlermeldungen sind aber auch beliebig definierbar, wobei die Texte den Nummern 0 - 255 zugeordnet werden können. Entsprechend der gewünschten Abbruchbedingung des Programmes wird die Fehlernummer angegeben.

30 IF A > 5 THEN ERROR 50

Wird während des Programmlaufes die Zeile 30 erreicht und der Wert der Variablen A ist größer als 5, dann wird die Zahl 50 als Fehlernummer gespeichert. Zu Beginn des Pro-grammes setzt man einen Sprungbefehl:

10 ON ERROR GOTO 1000

Im Unterprogramm ab Zeile 1000 kann dann der zugehörige Text ausgegeben werden.

1000 IF ERR = 50 THEN PRINT "A zu groß": GOTO ....

Nach dem Befehl ON ERROR GOTO ... darf kein CLEAR-Befehl enthalten sein.

 

2) ERR

a) Befehlsform: ERR = Fehlernummer

Die Variable ERR enthält die Fehlernummer, die mit der IF-Bedingung abgefragt werden kann.

1000 IF ERR = 32 THEN ERASE "A:TEST.BAS"

Falls das Programm TEST.BAS existiert, wird es gelöscht.

b) Befehlsform: ERR( # Kanal ) oder ERR(10)

Tritt ein Fehler bei der Benützung des angegebenen Kanals auf, so enthält die Funktion ERR(#Kanal) den Wert -1, sonst 0.

 

3) ERL Befehlsform: ERL = Zeilennummer

Die Variable ERL enthält die Zeilennummer der Programmzeile, in der der Fehler auftrat. Ein Fehler bei der Ausführung eines Direktbefehles ergibt den Wert 65535 für ERL.

 

4) RESUME:

Soll nach der Fehlerbehandlung in einem Unterprogramm mit der normalen Programmaus-führung fortgefahren werden, muß der Befehl RESUME das Unterprogramm abschließen. Dieser Befehl entspricht dem RETURN nach einem GOSUB.

a) Befehlsform: RESUME

Es wird der Befehl wiederholt, der den Fehler verursachte.

b) Befehlsform: RESUME Zeilennummer

Das Programm wird mit der angegebenen BASIC-Zeile fortgesetzt.

c) Befehlsform: RESUME NEXT

Das Programm wird nach dem Befehl fortgesetzt, der den Fehler verursachte.Am Anfang eines Unterprogrammes zur Fehlerbehandlung kann auch ein weiterer ON ERROR GOTO-Befehl stehen.

 

Beispiel zum wahlfreien Diskettenzugriff (RANDOM-DATEI)

30 CLEAR 5000:A$ = CHR$(64) ' 1000 Byte für String
40 GOSUB 440 ' Bildschirm frei
50 PRINT"Anlegen einer Datei = 1":PRINT
60 PRINT"Daten schreiben = 2":PRINT
70 PRINT"Daten lesen = 3":PRINT
80 PRINT"Ende = 0":PRINT
90 B = VAL(BYTE$(#0)):RL=0 ' Tastaturabfrage
100 : ON B GOTO 130,210,330 ' Verteiler
110 CLOSE:END
120 :
130 ' alle Records anlegen und auffüllen
140 GOSUB 460:OPEN#20,"R",NA$,L1 ' L1 =RL+4
150 FOR RN = 1 TO RZ:PRINT RN;
160 : S$ =STR$(RN)+STRING$(A$,RL)
170 : S1$=FIX$(MID$(S$,2,LEN(S$)),RL) ' Länge konstant
180 : PRINT#20@RN,S1$
190 NEXT RN:CLOSE#20:GOTO40
200 :
210 ' Record schreiben
220 GOSUB 440:PRINT"Record schreiben":PRINT
230 : IF RL=0 THEN GOSUB 460 ' Recorddaten
240 OPEN#20,"R",NA$,L1
250 : INPUT"Record-Nr. 0=Ende";RN
260 : IF RN = 0 THEN 310
270 : IF RN>RZ THEN 250 ' Recordnummer begrenzt
280 : INPUT"Eingabe:";E$
290 : IF LEN(E$)> RL THEN 280 ' Eingabe begrenzt
300 : PRINT#20@RN,E$:PRINT:GOTO 250
310 CLOSE#20:GOTO 40
320 :
330 ' Record lesen
340 GOSUB 440:PRINT"Record lesen":PRINT
350 : IF RL=0 THEN GOSUB 460 ' Recorddaten
360 OPEN#20,"R",NA$,L1
370 : INPUT"Record-Nr. 0=Ende";RN:GOSUB 440
380 : IF RN>RZ THEN GOSUB 440:PRINT"kein Record":GOTO 370
390 : IF RN=0 THEN 420
400 : INPUT#20@RN,E$: IF E$="" THEN PRINT"Keine Daten"
410 : PRINTE$:PRINT:GOTO 370
420 CLOSE#20:GOTO 40
430 :
440 PRINT CHR$(27);CHR$(69):RETURN ' Bildschirm frei
450 :
460 ' Recorddaten
470 INPUT"Dateiname ohne Dateityp";NA$:PRINT
480 INPUT"Laufwerk";LW$:PRINT
490 NA$=LW$ + ":" +NA$ +".rec"
500 : IF LOOKUP(NA$) THEN 570
510 IF B=3 THEN GOSUB 440:PRINT"Datei nicht vorhanden":
PRINT:GOTO 50
520 INPUT"Recordanzahl";RZ:PRINT
530 INPUT"Recordlänge";RL:L1=RL+4
540 OPEN#20,"R",NA$,13:D$=FIX$(STR$(RZ),5)+FIX$(STR$(L1),4)
550 PRINT#20@0,D$:CLOSE#20:RETURN
570 : IF B=1 THEN GOSUB 440:PRINT"Datei vorhanden":PRINT:
GOTO 50
580 OPEN#20,"R",NA$,13:INPUT#20@0,D$
590 : RZ = VAL(LEFT$(D$,5)):L1=VAL(RIGHT$(D$,3)):RL=L1-4
600 : PRINT"Recordzahl:";RZ;" Recordlänge:";RL:PRINT
610 CLOSE#20:RETURN

Erläuterungen dazu:

Was ist das besondere daran? Bei sequentiellen Dateien sind alle Daten hintereinander abgelegt, z. B. Mitgliedsdaten eines Vereines. Möchte man einzelne Daten verändern, sollten alle Daten im Kernspeicher zur Verfügung stehen. Bei einer Datei mit wahlfreiem Zugriff können z.B. nur der 2. und dann gleich der 200. Datensatz bestehen und auch bearbeitet werden, ohne daß dazwischen Datensätze vorhanden sein oder gelesen werden müssen. Man spricht von virtuellen Dateigrößen, da nur die tatsächlich vorhandenen Daten Speicherplatz auf der Diskette beanspruchen, also bei unserem Beispiel nur 2 Da-tensätze. Bei kleineren Diskettenkapazitäten gibt es jedoch dann erhebliche Probleme, wenn die virtuellen Dateien zu groß werden. Bei dem Beispielprogramm wird daher die Datei in voller Größe angelegt.

Eine wahlfreie Datei enthält Datensätze mit fest vorgegebener Satzlänge. Ein Datensatz aus einem Adressenprogramm kann z.B. so aufgebaut sein:

Anrede (max. 10 Zeichen), Name u.Vorname (max. 40 Zeichen),

Straße (max. 30 Zeichen), Postleitzahl und Wohnort (max. 50)

Ein Datensatz (auch Record genannt) enthält dann immer 130 Zeichen. Für jede Adresse gibt es einen Datensatz. Die Satzlänge kann nachträglich nur durch Übertragen der Daten in eine größere Datei abgeändert werden. Auch bekannte Datenbanksysteme wie DBASE arbeiten nach diesem Prinzip. Jede Teilinformation, z.B. Straße beginnt immer an der glei-chen Stelle im Datensatz. Eine andere Möglichkeit ist die Verwendung eines Markier-ungszeichens nach jeder Teilinformation, das dann allerdings mit dem INSTRING-Befehl gesucht werden muß.

Mit dem Beispielprogramm als Kernstück kann man z.B. ein Adressenprogramm auf-bauen. Eine sortierte sequentielle Datei enthält nur die Namen mit einer Schlüsselnummer, die die Satznummer der einzelnen Random-Dateien Adresse, Bankverbindung, Mitglieds-daten etc. enthält.

Programmbeschreibung: Das Programm ist in 5 Abschnitte gegliedert.

Nach Speicherreservierung und Bildschirmlöschung wird ein Menueplan angeboten.

2. Abschnitt: Zeile 130-190 * Record anlegen *

Nach Eingabe und Überprüfung der Recorddaten im Abschnitt Nr. 5 wird die Datei voll-ständig aufgefüllt, wobei die Recordnummer mit dem Zeichen CHR$(64) = "Klammeraffe" auf die eingegebene Recordlänge ergänzt wird. Somit werden bei einem Lesezugriff keine sinnlosen Daten gelesen. Die Recorddaten werden zusätzlich auf der Diskette im Record Nr. 0 abgespeichert.

3. Abschnitt: Zeile 210-310 * Record schreiben *

Nur bei Programmstart (Rl=0) werden die Recorddaten im Abschnitt Nr. 5 entweder von der Diskette gelesen oder eingegeben. Die eingegebenen Daten werden vor dem Schreibvorgang überprüft. Hier könnte man auch einen Lesezugriff einfügen, um bei vorhan-denen Dateien nicht Daten durch versehentliches Überschreiben zu vernichten.

4. Abschnitt: Zeile 330-420 * Record lesen *

Dieser Abschnitt ist dem 3. Abschnitt ähnlich aufgebaut, nur erfolgt jetzt ein Lesezugriff. Ist die Datei anfangs mit dem Programmabschnitt Nr. 2 angelegt worden, so werden jetzt definierte Daten gelesen.

5. Abschnitt: Zeile 460-620 * Recorddaten *

Dies ist eigentlich der wichtigste Abschnitt. Zunächst werden Dateiname und Laufwerk erf-ragt. Mit dem Befehl "lookup (Dateiname)" wird überprüft, ob die Datei existiert. Wenn nicht, wird bei einem Lesezugriff (b=3) ins Menue zurückgesprungen bzw. bei einem Schreibzugriff werden erst die Recorddaten ermittelt.

Recordanzahl und Recordlänge richten sich nach der Diskettenkapazität. Bei 360 KByte sind z.B. über 18000 Records mit 10 Zeichen Stringlänge oder auch 2600 Records mit 100 Zeichen möglich, wobei die Stringlänge maximal 250 Zeichen betragen kann. Die Records werden mit den Bytes 22h, 0Dh, 0Ah und 22h miteinander verbunden. Daher muß die ein-gegebene Länge der Records um 4 erhöht werden ( Zeile 530:L1=RL+4 ). Recordanzahl (RZ) und Recordlänge (L1) werden als String (D$) mit konstanter Länge ( 9 Zeichen ) abgespeichert. Ist die Datei vorhanden, so darf sie nicht aus Versehen mit Menueteil Nr. 1 durch Neuanlegen vernichtet werden; es erfolgt ein Rücksprung ins Menue (b=1). Nun kann Record Nr. 0 gelesen werden. Aus dem String (D$) werden Recordanzahl und Recordlänge ermittelt, danach erfolgt der Rücksprung in den jeweiligen Programmabschnitt.

V. HEBAS und Mathematik

Im ersten Teil sind die mathematischen Operatoren, Vergleichsoperatoren und logischen Operatoren in abnehmender Priorität aufgeführt.Im zweiten Teil folgen mathematische Funktionen, dann Umwandlungsbefehle wie Zahl zu String usw., im vierten Teil sind einige Beispiele zur Rechengenauigkeit aufgeführt. Alle Befehle können als Direktbefehl und in BASIC-Zeilen verwendet werden. Abschließend wird die Definition eigener BASIC-Funktionen mit dem DEF-Befehl beschrieben.

PRECISION: Befehlsform: PRECISION (Zeichenanzahl)

Ergebnisse von Berechnungen (z.B. Dezimalbrüche) werden mit maximal 11 Zeichen (ohne Punkt) ausgegeben. Diese Anzahl kann verringert werden, wobei die letzte ausgegebene Stelle gerundet ist. Intern wird mit 11 Zahlen weiter gerechnet. Die Zahl 0 oder keine Angabe nach dem Befehl ergeben wieder 11 Zeichen.

PRECISION 5 <CR> oder PRECISION (5)

Es werden bei Rechenergebnissen Zahlen mit maximal 5 Zeichen ohne Punkt ausgegeben. PRINT 10/7 <CR> ergibt die Zahl 1.4286, Print 100/7 <CR> ergibt 14.286. Mit PRECISION 0 <CR> wird nach PRINT 10/7 die Zahl 1.4285714286 ausgegeben.

1) Operatoren:

a) () Ausdruck in Klammern

b) ^ Exponentialoperator

c) - Negation (Zahl oder Ausdruck)

d) * Multiplikation / Division

e) Ganzzahldivision (Ö bei deutscher Tastatur)

f) MOD Modulus

g) + Addition - Subtraktion

h) = Gleichheitszeichen

<> ungleich

< kleiner als

> größer als

<= kleiner oder gleich =< gleich oder kleiner

>= größer oder gleich => gleich oder größer

i) NOT binäre Negation

j) AND logische UND-Verknüpfung

k) OR logische ODER-Verknüpfung

l) XOR logische Exklusiv-Oder-Verknüpfung

m) EQV logische Gleichwertigkeit

n) IMP logische Ungleichheit (Implizierung)

Bei Operatoren in einer Zeile nimmt die Priorität von links nach rechts ab. Alle logische Operationen i) - n) setzen ihre Operatoren in 16-Bit-Ganzzahlwerte um. Dabei ist der Bereich von 0 - 65535 (FFFF) oder von -32768 bis 32767 erlaubt (sonst Fehlermeldung: nicht erlaubt).

2) Mathematische Funktionen

Die Klammer nach dem BASIC-Befehl dient als Hinweis, daß immer ein Ausdruck in Klammern folgen muß, der auch durch eine numerische Variable oder durch einen arithmetischen Ausdruck ersetzt sein kann. Der berechnete Wert kann einer nummerischen Variablen zugewiesen werden. Bei Winkelfunktionen muß der Winkel in Bogenmaß (rad) angegeben werden. Die Umrechnung erfolgt durch Division des Winkelwertes (Grad = Altgrad) mit 180 und Multiplikation mit der Zahl Pi (1 Grad entspricht 0,017453.. rad). Die Variablen EE und PI enthalten fest gespeichert die Zahlenwerte für die Eulersche Zahl e und die Kreiszahl Pi.

a) ABS(: Befehlsform: ABS( Zahl oder numerische Variable )

Es findet eine Absolutwertbildung statt, d.h. negative Zahlen werden positiv. Exponent und Mantisse werden nicht verändert.

PRINT ABS(-523) <CR> Anzeige: 523
PRINT ABS(-5.1234 * 10^4) <CR> " : 51233.999999

Hier zeigt sich ein grundlegender Fehler der Binär-Interpreter (siehe 4) Rechengenauigkeit).

b) ATN(: Es liegt die Umkehrfunktion des Tangens, der Arcustangens vor. Das Ergebnis wird im Bogenmaß angegeben.

PRINT ATN(2) <CR> Anzeige: 1.1071487178

c) COS(: Es kann eine beliebige positive oder negative Zahl angegeben werden.

PRINT COS(0) <CR> Anzeige: 1
PRINT COS(60*PI/180) <CR> " : .5

d) EE: EE ohne Argument enthält die Eulersche Zahl e, die Basis der natürlichen Logarithmen.

PRINT EE <CR> Anzeige: 2.7182818285

e) EXP(: Es wird die Exponentialfunktion Y = e^X berechnet, wobei e die Eulersche Zahl 2,718..... darstellt.

PRINT EXP(88) <CR> Anzeige: 1.651636255E+38

Größere Zahlen X bewirken die Fehlermeldung "Ergebnis zu groß". Allerdings ist der Befehl PRINT EE^88 <CR> auch anwendbar. Bei verschiedenen Zahlen X zeigt sich dann, daß die mit beiden Befehlen für gleiche X-Werte erhaltenen Zahlen sich in der letzten Stelle unterscheiden.

PRINT EE^88 <CR> Anzeige: 1.6516362552E+38
A = 2 <CR> PRINT EXP(A) <CR> " : 7.3890560989
PRINT EE^A <CR> " : 7.389056099

f) FIX(: Dieser Befehl schneidet Zahlen hinter dem Dezimalpunkt ab und unterscheidet sich daher vom Befehl INT(, der die nächste größte Ganzzahl ermittelt, die kleiner oder gleich der als Argument verwendeten Zahl ist.

A = 123.567 <CR> PRINT FIX(A) <CR> Anzeige: 123
" INT(A) " " : 123
A = - 0.5 <CR> " FIX(A) " " : 0
dagegen: PRINT INT(A) <CR> " : -1

g) INT(: Mit dem Befehl INT( kann eine Zahl Z auf X Stellen gerundet werden.

E = INT(Z*10^X + 0.5)/10^X

h) LOG(: Es wird der natürliche Logarithmus (Logarithmus zur Basis e) berechnet.

PRINT LOG(1000) <CR> Anzeige: 6.907755279
PRINT LOG(EE) <CR> Anzeige: 1

i) LOG10(: Es erfolgt die Berechnung des dekadischen Logarithmus (zur Basis 10).

PRINT LOG10(1000) <CR> Anzeige: 3
PRINT LOG10(EE) <CR> " : .4342944819

j) MOD: Befehlsform: Dividend MOD Divisor

Es wird der Rest ermittelt, den man bei der Division des Dividenden durch den Divisor erhält.

PRINT 9 MOD 2 <CR> Anzeige: 1
" 8 MOD 2 <CR> " : 0

k) PI: Die Variable PI enthält den Wert der Kreiszahl.

PRINT PI <CR> Anzeige: 3.1415926536
PRINT PI/180 " : .01745329252
RINT 4*ATN(1) " : 3.1415926536

l) RND: Ohne Argument liefert der RND-Befehl Pseudo-Zufallszahlen zwischen 0 und 1, die einem festgelegten Algorithmus entstammen. Dadurch ergeben sich nach dem Start des BASIC-Interpreters immer dieselben Zahlen.

PRINT RND <CR> Anzeige: .26943583396

" " " " : .72796806886
" " " " : .089675555242

Der Befehl RANDOMIZE ergibt einen zufälligen Startpunkt der Pseudo-Zufallszahlenfolge (Z80: Zahl aus dem Refresh-Register R, 80X86: Timerwert).

RND(: Wird als Argument der Wert Null angegeben, wird erstmalig eine beliebige Zahl angezeigt und dann wiederholt.

PRINT RND(0) <CR> Anzeige z.B.: .5019531548
PRINT RND(0) <CR> " : .5019531548

Werte größer Null entsprechen dem RND-Befehl ohne Argument. PRINT RND(1) ergibt dieselben Zahlen wie PRINT RND. Negative Argumente bestimmen den Startpunkt der Zufallszahlenfolge. Die folgenden Zufallszahlensequenzen sind nach jedem BASIC-Start wiederum identisch.

A = RND(-280) <CR> PRINT RND <CR> Anzeige: 1.0207557995E-03

PRINT RND <CR> " : .94715060253
PRINT RND <CR> " : .826904723

Der Bereich ganzzahliger Zufallszahlen kann durch Angabe eines Anfangswertes AW und eines größeren Endwertes EW begrenzt weren.

B = INT((EW+1-AW)*RND+AW)

m) SGN(: Ist der im Argument enthaltene Zahlenwert positiv, Null oder negativ, so kann dies mit dem Befehl SGN ermittelt werden. Positive Werte ergeben als Ergebnis 1, negative -1, die Zahl 0 ergibt den Wert 0. Mit diesem Befehl kann eine Dezimalzahl in eine Binärzahl umgewandelt werden.

10 INPUT D
20 FOR I = 7 TO 0 STEP -1
30 PRINT SGN(X AND 2^I);
40 NEXT

n) SIN(: Das als Argument angegebene Bogenmaß wird in den Sinus umgerechnet.

SIN(45*PI/180) <CR> Anzeige: .70710678119

o) SQR(: Es wird die Quadratwurzel der als Argument angegebenen Zahl berechnet. Negative Zahlen ergeben die Fehlermeldung "nicht erlaubt". Höhere Wurzeln lassen sich durch den inversen Exponenten der Zahl X berechnen.

PRINT SQR(2) <CR> Anzeige: 1.4142135624
PRINT SQR(5)*SQR(5) <CR> " : 5
PRINT 10000^(1/4) " : 10 (4.WURZEL)

p) TAN(: Für den im Bogenmaß angegebenen Wert wird der Tangens berechnet.

PRINT TAN(45*PI/180) <CR> Anzeige: 1

3) Umwandlungsfunktionen Zahl-Zeichenkette und sonstige mathematische Befehle:

a) STR$(: Befehlsform: STR$ (Zahl oder nummerische Variable oder Ausdruck)

Die im Argument enthaltenen Zahlen werden mit diesem Befehl als Zeichenkette gekennzeichnet.

A$ = STR$(123456) <CR> PRINT A$ <CR> Anzeige: 123456
PRINT ASC(LEFT$(A$,1) <CR> " : 32

Das erste Zeichen der Zeichenkette A$ ist also ein Leerzeichen, was oft zu einem Fehlverhalten eines BASIC-Programmes führt.

b) VAL(: Befehlsform: VAL ( Stringvariable oder Zeichenkette)

Die Fehlermeldung "Datentypen (Zahl/String) vermischt" erscheint, wenn man einer nummerischen Variablen den Inhalt einer Zeichenkette zuordnen will. Mit dem Befehl VAL ist dies möglich. Es werden nur Zahlen am Anfang einer Zeichenkette ausgewertet.

A$ = "45.7" <CR> PRINT VAL(A$) <CR> Anzeige: 45.7
PRINT VAL("1234ABC") <CR> " : 1234
PRINT VAL("ABC1234") <CR> " : 0
PRINT VAL("123.45A") <CR> " : 123.45

c) HEX$(: Diese Stringfunktion wandelt eine als Argument angegebene Dezimalzahl (abgerundeter Wert) im Bereich von + 65535 bis - 65535 in einen String um, der die Sedezimalzahl enthält.

PRINT HEX$(1000) <CR> Anzeige: 03E8
A = 2020 <CR> PRINT HEX$(A) <CR> " : 07E4
PRINT HEX$(18.9) " : 0012

d) &: Dieses Zeichen muß sedezimalen Zahlen vorangestellt werden, sonst kommt z.B. bei dem Befehl INPUT A die Fehlermeldung "* Falsche Eingabe *" (siehe auch Kapitel I). Dagegen ergibt A = 3E8 bei PRINT A den Wert 300000000, also 3*10^8.

PRINT &3E8 <CR> Anzeige: 1000

10 INPUT"HEX-ZAHL";A$ Eingabe einer sedezimalen Zahl
20 PRINT VAL("&"+A$) mit Großbuchstaben, Ausgabe der Dezimalzahl

e) Ganzzahldivision: DIV

Wird eine Division mit diesem BASIC-Befehl durchgeführt, so entfällt die Verwendung des INT(-Befehles, wenn ein ganzzahliges Ergebnis benötigt wird.

PRINT 5 DIV 3 <CR> Anzeige: 1

4) Rechengenauigkeit des Interpreters

Die folgenden Beispiele zeigen, daß dieser BASIC-Interpreter weniger Probleme mit Rundungsfehlern hat als andere.

X = 66/20 <CR> PRINT INT(10*X)/10 <CR> Anzeige: 3.3
X = SQR(2) <CR> PRINT X^2 <CR> Anzeige: 2
PRINT LOG(0.99995) <CR> Anzeige: -5.0001249077E-05

Allerdings kann aufgrund der binären Zahlendarstellung bei einer Schleife von -1 nach 1 in Schritten 0.1 der Wert Null nicht erreicht werden.

10 FOR N = -1 TO 1 STEP .1 Nach der Anzeige der Werte
20 PRINT N -1, -.9 bis -.2 kommen
30 IF N=0 THEN PRINT "N = 0" -.099999999999 und
40 NEXT 1.1368683772E-12

5) Definition eigener BASIC-Funktionen

Mit diesen Befehlen können mathematische Funktionen definiert werden, die in einem Programm mehrmals für unterschiedliche nummerische Variablen anwendbar sind. HEBAS erlaubt sogar die Verwendung von Variablen für Zeichenketten bei entsprechenden Funk-tionen.

DEF FN: a) Befehlsform: DEF FN Name (Dummy-Variable) = math. Funktion

Funktionen müssen mit einem Namen gekennzeichnet sein, der mit FN beginnt und bis zu zwei weitere Zeichen (nach den Regeln für Variablen ausgewählt) enthalten kann.Beispiele für Funktionsnamen sind: FN Q, FNA9, FNZZ usw. Mehr als zwei weitere Zeichen nach FN sind möglich, werden aber nicht ausgewertet. Die Dummy-Variable dient als Platzhalter.

Beispiele für Funktionen:

DEF FN Q(X) = X*A
DEF FN A(X) = 1/COS(X)
DEF FN SR(V) = V/AC*20
DEF FN(X) = I+(K-1)*25+(L-1)*1000

Im Programm wird die am Programmanfang definierte Funktion mit dem Befehl FN Name (Variable) aufgerufen.

10 DEF FNQ(X) = X*A
20 INPUT A,B
30 PRINT FNQ(B)+5
40 C = FNQ(A):PRINT C

auch möglich: S1 = T(FNA(X)) oder PRINT W$(T(FNA(X)))

HEBAS erlaubt auch die Verwendung von mehreren Dummy-Variablen sowie von Funkionen für die Verarbeitung von Zeichenketten. Funktionen dürfen sich auch über mehrere BASIC-Zeilen erstrecken ("multiline"-Funktion), auch mit GOSUB-Befehlen. Dabei können andere Funktionen ebenso wie die gerade bearbeitete aufgerufen werden.

b) Befehlsform:

DEF FN Name (Dummy 1, Dummy 2, ......., Dummy n)

Funktion in mehreren BASIC-Zeilen

FNEND (Variable für Funktionswert)

Die Funktion kann jedoch nur einfache Funktionen mit der ersten Befehlsform enthalten, keine "multiline"-Funktion. FNEND beendet die Funktion und übergibt den berechneten Ausdruck der angegebenen Variablen, die vom selben Typ (Zahl oder Zeichenkette) wie die Funktionsvariablen sein muß.

Beispiel 1)

10 DEF FNFAC(I)
20 IF I = 0 THEN FNRETURN 1 REM FAC(0) =1
30 FNEND FNFAC(I-1)*I REM FAC(I) = FAC(I-1)*I

Beispiel 2)

10 DEF FN REP$(I$,I)
20 J$ = ""
30 IF I<=0 THEN FNRETURN J$
40 FOR J = 1 TO I
50 J$ = J$ + I$
60 NEXT
70 FNEND J$
80 :
90 INPUT"ZEICHEN, ANZAHL";I$,I
100 PRINT FNREP$(I$,I)

Der Befehl FNRETURN (Variable für Funktionswert) beendet die Funktion und übergibt einen bestimmten Wert an das Programm. Mehrere FNRETURN-Befehle sind erlaubt.

** Achtung **

Ein Syntaxfehler in der Definition der Funktion wird erst beim Aufruf der Funktion erkannt, wobei dann aber die Zeilennummer der BASIC-Zeile ausgegeben wird, in der der Funktionsaufruf steht und nicht die Zeile mit der Definition.

Wird die Funktion aufgerufen, ohne daß eine Definition der Funktion stattgefunden hat, erfolgt die Fehlermeldung "USER FN CALL fehlt Zeile XY".