BASIC-Compiler

Zeichenkettenverarbeitung

Der JKCEMU-BASIC-Compiler bietet eine weitreichende Unterstützung für die Verarbeitung von Zeichenketten (Strings). Diese Unterstützung umfasst String-Variablen zur Speicherung, Funktionen zur Verarbeitung sowie Anweisungen zur Ein- und Ausgabe von Zeichenketten. Die Hinweise zur Zeichenkettenverarbeitung unterteilen sich in folgende Abschnitte:

1. Längenbegrenzung einer Zeichenkette

Die interne String-Verarbeitung kann Zeichenketten bis zu einer Länge von 255 Zeichen verarbeiten. Längere Zeichenketten werden abgeschnitten.

Die Längenbegrenzung gilt nicht für String-Literale, die Funktionen INSTR, LEN, LTRIM$ und MEMSTR$ sowie für die Ausgabe von Zeichenketten.

2. String-Literale

Ein String-Literal ist eine Zeichenkettenkonstante, d.h., die Zeichenkette wird schon im BASIC-Quelltext geschrieben. Ein String-Literal ist eine Folge von Zeichen, die in doppelten Hochkommas eingeschlossen ist.

Syntax: " <Zeichenfolge> "

3. String-Variablen

String-Variablen dienen zur Speicherung von Zeichenketten, wobei auch hier die Beschränkung auf maximal 255 Zeichen gilt. Sowohl einfache als auch Feldvariablen können zur Speicherung von Zeichenketten verwendet werden.

Der Name einer String-Variable muss mit einem $-Zeichen enden.

4. String-Funktionen

Der Begriff String-Funktion hat eine Doppelbedeutung. In semantischer Hinsicht ist damit eine Funktion gemeint, bei der Zeichenketten eine Rolle spielen, d.h., bei der eine Zeichenkette übergeben oder zurückgeliefert wird. In syntaktischer Hinsicht sind nur das String-Funktionen, die eine Zeichenkette zurückliefern. Diese Funktionen tragen als letztes Zeichen ein $ in ihrem Namen.

Einige der String-Funktionen erzeugen eine neue Zeichenkette. Dafür wird Speicherplatz benötigt, und zwar nur kurzzeitig, denn nachdem die aktuelle Anweisung abgearbeitet wurde, ist die so entstandene Zeichenkette verarbeitet oder im Fall einer LET-Anweisung in einer Variable gespeichert worden. Wie auch immer, für die interne Zeichenkettenverarbeitung wird temporärer Speicher benötigt. Der JKCEMU-BASIC-Compiler verwendet dafür einen statischen String-Puffer. Im Gegensatz zum dynamischen Allokieren und Freigeben von Speicherbereichen ermöglicht dieses statische Verfahren die Erzeugung von schnellem und kompaktem Programmcode. Allerdings bedingt das auch einige kleinere Einschränkungen: Der statische String-Puffer kann nämlich zu einem Zeitpunkt nur von einer Funktion verwendet werden. Aus diesem Grund können solche Funktionen nicht in sich geschachtelt werden, oder anders ausgedrückt: Wenn Funktionen in sich geschachtelt werden, dann darf nur maximal eine dabei sein, die den statischen String-Puffer verwendet. Folgende Funktionen verwenden den internen String-Puffer:

Wird die Beschränkung bzgl. der Schachtellung von String-Funktionen nicht eingehalten, gibt der Compiler eine entsprechende Fehlermeldung aus. Allerdings kann ja der Bedarf trotzdem bestehen, diese String-Funktionen in sich zu schachteln. In dem Fall muss man eine Variable zur Hilfe nehmen: Man speichert das Ergebnis der inneren String-Funktion in eine Variable und verwendet diese dann als Argument in der äußeren, z.B.:

Problem (Compiler-Fehler)Lösung
A$="Das ist ein Beispiel."
B$=TRIM$(MID$(A$,4,5))
A$="Das ist ein Beispiel."
M$=MID$(A$,4,5)
B$=TRIM$(M$)


5. String-Ausdrücke

Der BASIC-Compiler unterscheidet zwischen einfachen und komplexen String-Ausdrücken. Ein komplexer String-Ausdruck besteht aus mit dem Plus-Operator zusammengeketteten einfachen String-Ausdrücken. Ein einfacher String-Ausdruck ist entweder ein String-Literal, eine String-Variable oder der Aufruf einer String-Funktion.

Komplexe String-Ausdrücke sind nur bei Ausgaben und bei der Zuweisung einer Variable erlaubt, z.B.:

A$="Hallo"
B$="Welt"
C$=A$+SPACE$(1)+B$
LABEL "--"+C$+"--"

Als Argumente bei Funktionsaufrufen sind nur einfache String-Ausdrücke erlaubt. Gegebenfalls muss auch hier eine Variable zur Zwischenspeicherung verwendet werden.

6. Optimierungen

6.1. Vermeidung von unnötigen Zuweisungen

Die Zeichenkettenverarbeitung benötigt deutlich mehr Rechenzeit als die Verarbeitung von Integer-Werten. Insbesondere die Speicherung von Zeichenketten in String-Variablen geht sehr zu Lasten der Performance, da je nach Bedarf dynamisch Speicher allokiert und wieder freigegeben werden muss. Aus diesem Grund sollten die Anzahl der Variablenzuweisungen möglichst gering gehalten bzw. unnötige Zuweisungen vermieden werden. Des Weiteren sollten bei der Arbeit mit einzelnen Zeichen diese nach Möglichkeit in Integer-Werte umgewandelt und dann weiterverarbeitet werden. In der folgenden Tabelle werden am Beispiel der Tastaturabfrage mit INKEY$ diese beiden Optimierungsmöglichkeiten gezeigt:

Langsamer Code Schneller Code Noch schnellerer Code
E$=INKEY$
IF E$="A" THEN ...
IF INKEY$="A" THEN ...

→ Variablenzuweisung eingespart
IF ASC(INKEY$)='A' THEN ...

→ Integer- statt String-Vergleich

Achtung! Sobald man im BASIC-Programm nur eine einzige String-Variable und damit nur eine einzige Zuweisung einer String-Variable verwendet, wird das compilierte BASIC-Programm auch den gesamten Programmcode für die interne dynamische Speicherverwaltung enthalten. Wenn Sie also im Programm keine Zeichenkettenverarbeitung benötigen und nur wegen Funktionen wie z.B. INKEY$ eine String-Variable verwenden würden, dann sollten Sie die o.g. Optimierung nicht nur aus Gründen einer besseren Performance, sondern auch wegen einem deutlich kleineren Binärprogramm vornehmen.

6.2. Zugriff auf Teile einer Zeichenkette

Für die Extraktion eines Teils einer Zeichenkette gibt es die Funktion MID$. Dabei wird intern die extrahierte Teilzeichenkette als neue Zeichenkette in einem anderen Speicherbereich bereitgestellt. Möchte man nur auf einzelne Zeichen einer Speicherkette zugreifen, kann man das auch unter Umgehung der String-Verarbeitung und damit performanter mit den Funktionen STRPTR und PEEK tun. Man muss allerdings selbst darauf achten, nicht das Ende der Zeichenkette zu überschreiten. Dieses wird mit einem Nullbyte markiert. Das Beispiel zeigt, wie man in einer Zeichenkette die Anzahl der Großbuchstaben zählen kann:

T$=...
A=STRPTR(T$)
N=0
DO
  B=PEEK(A)
  A=A ADD 1
  IF B=0 THEN EXIT
  IF B>=65 AND B<=90 THEN N=N+1
LOOP
PRINT N;"Groessbuchstaben enthalten"