Basic optimieren - Teil 3
mad/os

Hier nun wie versprochen ein weiterer Teil meines kleinen Kurses für alle Basic-Programmierer. Die folgenden Tips sind, ähnlich wie beim ersten Teil, unabhängig voneinander anwendbar. Kleine Spezialitäten, Sonderbefehle und mathematische Raffinessen...

1. TALLY: Oft soll ganz einfach überprüft werden, ob ein String in einem anderen vorkommt. Die Funktion INSTR(H$,T$) bietet sich dafür besonders an. Eine weitere Möglichkeit stellt die Funktion TALLY(H$,T$) dar, die das Vorkommen von T$ in H$ zählt. Der Effekt in einer Bedingung ist identisch, da beide Befehle eine Null liefern, wenn T$ nicht in H$ vorhanden ist. Durch die Verwendung von TALLY wird die Programmdatei jedoch jedesmal etwa 150 Bytes verkleinert. Leider wird TALLY auch langsamer ausgeführt, vor allem bei langen Strings, in denen der gesuchte Teil mehrmals vorkommt. In den meisten Fällen dürfte das jedoch egal sein.

2. FIX: Wenn es darum geht, eine Zahl ihrer Nachkommastellen zu berauben, dann gibt es dafür zwei Wege. Die Einen bevorzugen die dafür bestimmte Funktion FIX, die Anderen verwenden lieber INT. Und seltsamerweise ist das auch egal. Ich konnte keinen einzigen Unterschied zwischen FIX und INT feststellen. Auch die Geschwindigkeit und Größe der erzeugten Programmdatei sind identisch.

3. SPACE$: Die Funktion SPACE$ liefert einen String zurück, der aus einer wählbaren Anzahl Leerzeichen besteht. Diese Funktion sollte aber mit Bedacht eingesetzt werden. Wenn man zum Beispiel statt PRINT SPACE$(3) die Variante PRINT "___" verwendet, werden die Leerzeichen schneller ausgegeben und die Programmdatei wird ein wenig kleiner. SPACE$ bringt also nur dort etwas, wo die Anzahl tatsächlich verändert werden soll.

4. PRINT: Und hier ein Tip, der nicht das Programm sondern die Eingabe beschleunigt. Schreibt statt des Befehles PRINT ganz einfach ein Fragezeichen! Zum Beispiel ist die Zeile PRINT A$ identisch mit ? A$, aber es müssen vier Zeichen weniger getippt werden.

5. NOT: Oft werden in einem Programm besondere Variablen verwendet, die zwischen zwei Zuständen hin und her springen sollen. So könnte die Variable X zum Beispiel anzeigen, ob eine Funktion ein- oder ausgeschaltet ist. Bisher habe ich so etwas mit der Zeile IF X = 1 THEN X = 0 ELSE X = 1 realisiert.

Wesentlich eleganter und professioneller sind jedoch die Formen X = 1 - X und X = NOT X, die zudem noch schneller ausgeführt werden. (Ein herzliches Dankeschön an LeidPen für diesen Trick.) Diese Formen eignet sich jedoch ausschließlich für den Wechsel zwischen Null und Eins! Für andere Kombinationen habe ich die Lösung X = A + B - X ersonnen. Für A und B werden die beiden möglichen Zustände der Variablen X eingetragen. Diese Ausdrücke können natürlich auch in eine Konstante verrechnet werden. Außerdem muß X unbedingt mit einem der beiden Werte initialisiert werden! Ein Wechsel zwischen den Zahlen 25 und 50 könnte demnach so aussehen:

X = 25
DO
  PRINT X,
  X = 25 + 50 - X         'oder auch: X = 75 - X
LOOP WHILE INKEY$=""

6. LINE INPUT: Der Befehl INPUT ist sehr unflexibel und in größeren Programmen praktisch nicht verwendbar. Die Variante LINE INPUT bietet schon etwas mehr Komfort, weil dann auch Kommas eingegeben werden können. Außerdem wird vor der Eingabe kein Fragezeichen angezeigt.

7. INKEY$: Für professionelle Programme muß man leider selbst eine komfortable Eingabefunktion schreiben. Entweder verwendet man dafür den Befehl INPUT$ oder die wirklich universelle Lösung INKEY$.

SUB Eingabe (Zeile, Spalte, L, Text$)
E$ = Text$
DO
  LOCATE Zeile, Spalte: PRINT SPACE$(L);
  LOCATE Zeile, Spalte, 1: PRINT E$;
  I$ = "": WHILE I$ = "": I$ = INKEY$: WEND
  SELECT CASE I$
    CASE CHR$(32) TO CHR$(254)
      E$ = LEFT$(E$ + I$, L)
    CASE CHR$(8)
      E$ = LEFT$(E$, ABS(LEN(E$) - 1))
    CASE CHR$(13): Text$ = E$: EXIT DO
    CASE CHR$(27): EXIT DO
  END SELECT
LOOP: LOCATE , , 0
END SUB

Dieses Unterprogramm stellt einen vollwertigen Ersatz für den Befehl INPUT dar. Zusätzlich wird durch die Variable L die mögliche Länge der Eingabe begrenzt. Weitere Funktionen, wie zum Beispiel eine Editierfunktion die auch auf die Pfeiltasten reagiert, sind mit geringfügig höherem Aufwand ebenso realisierbar.

8. ASCII: Die Zuordnung, welche Taste welchen Code verursacht, ist nicht immer logisch. Mit einem kleinen Programm kann man das aber jederzeit selbst ausprobieren.

DO
  I$ = "": WHILE I$ = "": I$ = INKEY$: WEND
  PRINT ASC(I$)
  IF LEN(I$)1 THEN ? , ASC(MID$(I$, 2))
LOOP UNTIL I$ = CHR$(27)

Tasten mit normalen Zeichen liefern per INKEY$ einen einzelnen ASCII-Code zurück, der diesem Zeichen entspricht. Bei Sondertasten wie zum Beispiel den Pfeilen werden jedoch zwei Codes geliefert. Davon ist der erste immer eine Null. Innerhalb des Programmes kann das sehr einfach durch einen Befehl wie zum Beispiel IF I$=CHR$(0,59) THEN ... oder CASE CHR$(0,75) abgefragt werden.

9. INP(&H60): Vor allem bei Spielen ist die Abfrage der Tastatur mit INKEY$ sehr unbefriedigend. Eine mögliche Alternative bietet der Port &H60, der die Scancodes der Tastatur direkt abfragt. Diese Variante hat neben dem Vorteil, daß keine Verzögerungen auftreten, auch mehrere Nachteile. So muß zum Beispiel sichergestellt werden, daß der Tastaturpuffer nicht überläuft. Außerdem kann sich ein mangelhaftes Programm sehr leicht in einer Endlosschleife verfangen. Und weil die Signale der Tastatur vom Programm abgefangen werden, läßt es sich nicht mehr abbrechen! Weder Strg+Untbr noch die Notlösung Strg+Alt+Entf funktionieren dann noch!

DEFINT A-Z: CLS
DO
  A=INP(&H60)                             'Tastaturport auslesen
  WHILE LEN(INKEY$): WEND
  IF AB THEN
    SELECT CASE A
      CASE 224: COLOR 14                   'das Vorsatzbyte gelb
      CASE 127: COLOR 2          'losgelassene Tasten dunkelgrün
      CASE ELSE: COLOR 10             'gedrückte Tasten hellgrün
    END SELECT
    ? RIGHT$("00000000"+BIN$(A), 8), A
    B=A
  END IF
LOOP UNTIL A=1            'mit Esc wird das Programm abgebrochen

Dieses Beispielprogramm zeigt die Scancodes der gedrückten und losgelassenen Tasten am Bildschirm an. Wenn es unter QBasic laufen soll, muß lediglich der Befehl BIN$ entfernt werden. Hellgrüne Zahlen zeigen an, daß gerade eine Taste gedrückt wurde. Dunkelgrüne Tasten wurden gerade losgelassen. Und das Vorsatzbyte vieler Sondertasten wird gelb angezeigt.

mad/os