R.T.Russell Home Page

Chapter 13 - Other Ways of Entering Information




GET and GET$

The problem with INPUT is that you have to enter the keys you want and then press return. If you are waiting for the user to enter information that the program can act on, like the radius of a circle, that's ok but there are times when the keyboard is used for other purposes. GET waits for a key to be pressed and returns the ASCII code for that key, without printing it back to the screen. You can use this to assign the key pressed to a variable, or just to wait for a key press after displaying a screenful of information.

REM GET demo
PRINT "Press any key to continue"
Key% = GET
PRINT "Code for key pressed: ";Key%
END
GET takes account of cursor keys, function keys etc. The codes returned are given in the help files under GET / GET$, or you can keep the above program handy and run it when you need to find the code for Alt-F1 or whatever.

GET$ returns a single character string representing the key the user pressed. As with its twin above, a value is returned for each key pressed including function keys etc. These return characters above 127, so if you try to print them, you may get strange results. Try this little program and verify that it does return different values for F1, Shift+F1, Ctrl+F1 and Alt+F1.

REM GET$ demo
Key$=GET$
PRINT Key$,ASC(Key$)
END
Using GET$ and GET allows us to vet the input that the user is making so we can check that keys being pressed are valid. This gets around a problem with INPUT. BASIC waits for return to be pressed and then tries to deal with the result, which often it can't. This is a useful little routine that only allows the user to enter numbers 0 to 9 and ignores other keys.
REM Number filter
Total$=""
PRINT "Type your number or Enter to finish"
REPEAT
  Key$=GET$
  IF Key$ >="0" AND Key$ <="9" THEN
    Total$=Total$+Key$
    PRINT TAB(0,1);Total$;
  ENDIF
UNTIL ASC(Key$)=13
PRINT '"You entered: ";VAL(Total$)
END
INKEY and INKEY$

INPUT, INPUT LINE, GET and GET$ all wait for a key to be pressed before the program continues. We will now put two commands under the microscope that allow us to specify an amount of time we can wait before BASIC gives up and continues. The functions INKEY and INKEY$ can both take a number which specifies the amount of time to wait in centiseconds (just like our friend the WAIT command). If a key is pressed in this time, the function returns its value just as GET and GET$. INKEY returns the ASCII value and INKEY$ returns a single character string. The codes for the extended keys (function, cursor etc.) are just the same as GET and GET$, which is a good thing, really. If no key was pressed in the time, –1 or an empty string is returned.

REM INKEY demo
PRINT "Press a key or wait 5 seconds"
REM 500 = 5 seconds / 0.01
Key%=INKEY(500)
IF Key%<>-1 THEN
  PRINT "You pressed ";Key%
ELSE
  PRINT "You pressed nothing"
ENDIF
END
If the time value is 0, the INKEY twins return immediately without waiting. Most useful in games where you want to have the aliens lurching across the screen without waiting for the player to move. This modest example counts the number of repeats of a loop until a key pressed.
REM INKEY$
Count% = 0
REPEAT
  WAIT 50 : REM Delay for 0.5 seconds
  Count% = Count%+1
UNTIL INKEY$(0)<>""
PRINT "You waited ";Count%/2;" seconds"
END
INKEY (not INKEY$) has an extended functionality in that it can be used to test for individual keys being pressed. To do this, we give it a negative argument. The table of values used to represent the required key is not related to the ASCII code and is given in full in the help files under INKEY / INKEY$. When used in this way, it returns immediately with a value of TRUE (–1) or FALSE (0) depending on whether the required key was pressed. Again, this is really good for games:
REM INKEY to detect individual keys
PRINT "Use left and right, space and x"
REPEAT
  pause% = INKEY(1)
  IF INKEY(-26) PRINT "Move left"
  IF INKEY(-122) PRINT "Move right"
  IF INKEY(-99) PRINT "FIRE!!!"
UNTIL INKEY(-67)
END
Note that pressing each key can generate more than one message as the program is testing each key many times a second, not just once every time the key is held down. You can also try holding the left and fire keys at the same time to see if this works.

The pause%=INKEY(1) line has two functions: it prevents the program 'hogging' the computer's processor (which can slow down other programs or cause a laptop's battery to run down more quickly) and it stops the keyboard buffer (see below) filling up if you press the keys many times. If the buffer fills, the computer will complain by beeping.

The Keyboard Buffer

BASIC will accept key presses at any time, not just when you're looking for them with INPUT etc. To ensure that no keystrokes are missed, there is a little queue into which all key presses are inserted. When BASIC uses INKEY / GET$ etc. it doesn't inspect the keyboard directly, but pulls the first entry it finds in this keyboard queue or buffer, as it is generally known. If you press a key when the program is not expecting it, the key pressed is added to the buffer and sits there until the next GET or INKEY comes along and reads it. As a result of this, the key you get might not be the key you were expecting, depending on if there was any junk left over in the keyboard buffer.

It is a very useful thing to be able to clear the buffer at will before making a call to GET or INKEY. All we have to do is loop until INKEY returns nothing:
REPEAT UNTIL INKEY(0)=-1
As a demonstration, run this little program.
REM Keyboard buffer
PRINT "Press a key to continue"
A%=GET
PRINT "Ok, now press another, quickly"
WAIT 500
PRINT "Press a key to continue"
REM REPEAT UNTIL INKEY(0)=-1
A%=GET
PRINT "Program finished"
END
If you press a key twice before the 5 second delay has expired (line 5) the key is added to the buffer and sits there. The next call to GET in line 8 then reads this directly without waiting and the program ends. Take the REM out of line 7 and try again. Now the buffer is emptied before the second call, so all is well.

This might seem like a lot of fuss over something so small, but unless you are aware of it, it'll trip you up someday and you'll thank me for it. Honest.

Exercises

1) Modify the number filter program to accept one (and only one) decimal point in the number. If you're feeling ambitious, add a further modification to intercept backspace and delete the last character, if any, from the string. You'll need to print a space after the string to erase the character from the screen.
2) Make a simple drawing program. Use X% and Y% in a TAB statement to plot an 'X' on the screen. When you press the arrow keys, adjust X% or Y% according to the key pressed. For example, if you press left, decrease X%, down - increase Y%. Plot an 'X' at the new position so you can leave a trail on the screen. Restrict the area in which you can draw to a 20 * 20 grid.

Left CONTENTS

CHAPTER 14 Right


Best viewed with Any Browser Valid HTML 3.2!
© Peter Nairn 2006