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.