In vielen Programmen treffe ich immer wieder folgende, wie Sie auch noch erkennen werden, effektiv falsch programmierten Tastaturabfrageschleifen:
' So besser nicht!
SCREEN 0: WIDTH 40, 25: CLS
x% = 20
y%= 13
DO
LOCATE y%, x%
PRINT "*";
DO
t$ = INKEY$
LOOP WHILE t$ = ""
LOCATE y%, x%
PRINT " ";
' hier wird etwas ganz FATALES gemacht!
IF LEN(t$) = 2 THEN
t$ = RIGHT$(t$, 1)
END IF
SELECT CASE t$
CASE "H" ' Pfeil oben
IF y% > 1 THEN
y% = y% - 1
ELSE
BEEP
END IF
CASE "P" ' Pfeil unten
IF y% < 25 THEN
y% = y% + 1
ELSE
BEEP
END IF
CASE "K" ' Pfeil links
IF x% > 1 THEN
x% = x% - 1
ELSE
BEEP
END IF
CASE "M" ' Pfeil rechts
IF y% < 40 THEN
x% = x% + 1
ELSE
BEEP
END IF
CASE CHR$(27) ' Esc-Taste
' Verlassen => nichts tun!
CASE ELSE ' übrige Tasten
BEEP
END SELECT
LOOP UNTIL t$ = CHR$(27)
Um den Fehler genau zu verstehen, kommt eine kleine Zusatzaufgabe: Versuchen
Sie das obige Programm um eine Funktion »Pause« zu ergänzen,
welche mit Umschalt+P, also
dem grossen P aufgerufen werden soll! Ausserdem fällt Ihnen auch auf, dass
man bei dieser Variante bei aktiviertem Caps Lock den
Stern auch mit H, K, M und P steuern kann, was in
diesem Fall sicherlich nicht erwünscht wird (spezieller
Seiteneffekt). Sie sehen nun hoffentlich selber, dass Sie mit diesem
RIGHT$ in der Programmitte den von QuickBASIC eindeutigen
Tastencode zerstören. Und genau dies sollten Sie nicht tun!
' So macht man es richtig!
SCREEN 0: WIDTH 40, 25: CLS
x% = 20
y%= 13
DO
LOCATE y%, x%
PRINT "*";
DO
t$ = INKEY$
LOOP WHILE t$ = ""
LOCATE y%, x%
PRINT " ";
SELECT t$
CASE CHR$(0) + "H" ' Pfeil hoch
IF y% > 1 THEN
y% = y% - 1
ELSE
BEEP
END IF
CASE CHR$(0) + "P" ' Pfeil unten
IF y% < 25 THEN
y% = y% + 1
ELSE
BEEP
END IF
CASE CHR$(0) + "K" ' Pfeil links
IF x% > 1 THEN
x% = x% - 1
ELSE
BEEP
END IF
CASE CHR$(0) + "M" ' Pfeil rechts
IF y% < 40 THEN
x% = x% + 1
ELSE
BEEP
END IF
CASE CHR$(27) ' Esc-Taste
' Beenden => nichts tun
CASE ELSE ' übrige Tasten
BEEP
END SELECT
LOOP WHILE Drinbleib%
Auf diesen Aspekt müssen Sie besonders sorgsam achten, wenn Sie einen
Ersatz für LINE INPUT für Bildschirmmasken,
wie unter Programmierung professioneller
Bildschirmmasken beschrieben, erstellen möchten, da dort die
regulären Zeichen (Buchstaben, Zahlen und Satzzeichen) sowie die
Spezialtasten wie Pos1 und Ende usw.
gleichzeitig abgefragt werden müssen.
Viele QuickBASIC-Programmierer begehen den anfänglich beschriebenen Fehler dadurch, weil sie den Tastencode als Zahl auswerten möchten:
' So nicht! DO t$ = INKEY$ LOOP WHILE t$ = "" taste% = ASC(RIGHT$(t$, 1)) ' Ganz FATAL falsch! SELECT CASE taste% CASE 72 ' Pfeil hoch ' .. CASE 75 ' Pfeil links ' .. ' .. END SELECT
Die Auswertung mittels ASCII-Wert kann man wie folgt lösen:
' So ist es richtig! DO t$ = INKEY$ LOOP WHILE t$ = "" IF LEN(t$) = 2 taste% = ASC(RIGHT$(t$, 1)) OR 256 ELSE taste% = ASC(t$) END IF ' das normale Umschalt+P hat jetzt 72 SELECT CASE taste% CASE 328 ' Pfeil hoch ' .. CASE 331 ' Pfeil links ' .. ' .. END SELECT
Bei den dortigen Sprachen lesen Sie bekanntlich aus conio.h mit
getch() üblicherweise nur ein einzelnes Byte ein:
int lies_taste(void) {
int code;
if (kbhit()) {
code = getch();
if(code == 0) /* Spezialtaste */
code = 256 | getch();
} else
code = -1;
return code;
}
Genau auf demselben Prinzip arbeitet auch INKEY$ sowie das
letzte BASIC-Beispiel.