Perfect Commodore INPUTs
A one-line cure for accidental program exits during keyboard input.
Blaine D. Standage, Orange, CA
Solve the problem of inputting from the VIC, PET/CBM, 64 keyboard once and for all with one simple line of BASIC code. Why clutter your program with complex subroutines when there is a better way?
I waited a long time for someone to write this article, but no one did. Meanwhile, I kept seeing involved subroutines offered as solutions to the "input problem."
The "problem" is that when you hit the RETURN key in response to an INPUT statement without first giving a Commodore computer some data, it promptly dumps you out of the program – often a very undesirable result. The same thing happens if you accidentally hit the STOP key while the computer is in a GET loop waiting for data. (10 GET A$: IF A$ = " " THEN 10). Since most of the proposed solutions use GET loops, it seems that they only move the problem by a keywidth rather than solve it.
Following the KISS (Keep It Simple, Sam) method, let's define our ideal objectives and try to take a completely fresh approach to the problem.
Avoid Subroutines
The highest probability of an operator disrupting a program occurs when he is responding to an INPUT or a GET command. At that time we need to simplify his task by preventing him from accidentally halting the computer.
To keep it simple for the programmer, we need to avoid subroutines, particularly large ones or those written in machine language which may require some form of special handling.
As to the fresh approach, remember that when a thing doesn't work the way you want it to, one alternative is to simply not use it! Oddly enough, that is exactly the way out of this problem. Don't use INPUT or GET.
When we remove INPUT and GET from the instruction list, we are left with only two commands which might take their place, INPUT# and GET#. But aren't they for use with external devices like tape or disk drives? Not exactly. They are the complete form of the commands for inputting. INPUT and GET are just simplified forms which allow easy access to the keyboard.
Using GET#
The results of investigating GET# showed that, overall, it operates very much like GET. We can't completely solve our problems with it because the program can always be halted with the STOP key.
The most obvious difference occurs when we press a non-numeric key while trying to get a numeric value (i.e., GET#1 A). The computer responds with:
?SYNTAX ERROR READY.
"SYNTAX ERROR" doesn't seem a reasonable response, and I haven't found out why it happens. Nor can I see any way to take advantage of it, but maybe someone else can.
Perhaps the biggest potential advantage to GET# becomes evident by recalling that we commonly open output files to both the printer and the screen. We then direct the PRINT# output by selecting the appropriate file with a variable value. Similarly, the keyboard could be included in a selectable group of input devices through the use of GET# or INPUT# with a variable defining the file number.
How About INPUT#?
Using INPUT# proved to be the answer, but a lot was learned along the way.
When you enter and run the simple program:
10 OPEN 1, 0 20 INPUT#1, A$ : PRINT A$ : GOTO 20
all the inputs are echoed back, and there seems to be no way out of the program. RETURNS are ignored, and the STOP key has no effect. Most of my test group (victims, to hear them tell it) decided there was no way to regain control short of cycling computer power. Only the most determined ones discovered that the SHIFTed RUN/STOP would cause a break. (On VIC, this would be Commodore Key/RUN\STOP.) This combination is so unlikely in an input situation that we can almost disregard it as an accidental response.
When I first performed this experiment, my impulse was to consider the problem solved and go on with my programming. What a variety of interesting possibilities I would have missed!
Go to your computer and follow this easy exploration of INPUT#. It will be worth your time.
First, enter the following test program. Use the line numbers as shown because we will be adding to the program.
10 OPEN 1,0 20 : 30 INPUT#1, A 70 PRINT A 80 FOR J = l TO 1500: NEXT J 90 GOTO 20
Line 80 has no direct bearing on the problem. It gives you a way to halt the program by providing time to press the STOP key after an input.
When the program is run, notice that the customary question mark is not printed. If we want the question mark we must include it in the input prompting. But we are also free to leave it out for inputs where it is not appropriate.
Next, enter a few numbers and notice they are printed back on the same line as the input even though we made no special provision for that. It seems we will have to print a "return" after inputting to get back to the left margin.
Now press RETURN without any data, and the computer responds as though you had entered a zero. Here is a feature we have wished for. But don't get too excited yet, because when we enter non-numeric characters the computer responds:
?FILE DATA ERROR IN 30 READY.
and we see that we can't solve our problem with a numeric variable input. Why a "file data error"? Remember, the computer thinks it is getting data file inputs from an external device.
Now let's make some changes to our test program to correct the defects we have seen. Unlike INPUT, the INPUT# command has no provisions for built-in prompting, so we must provide it in a separate PRINT command (line 20).
20 PRINT "ENTER DATA ? " 30 INPUT#1, A$: PRINT 70 PRINT A$
Running this now reveals that we won't stop the program during the input process either with a bad input or with the STOP key. Also notice that a simple RETURN is interpreted as a null (nothing there) string. We can really make use of this feature. (You can prove that the string is really null by manually creating a field of characters, a line of reversed spaces, for example, where the printing will be done. Observe that they are not altered during the execution of line 70.)
Several Handy Features
Of course, we neglected the semicolon at the end of line 20 to force the input to follow its prompt, so let's put it in and re-test.
20 PRINT "ENTER DATA?";
Careful now — something important has changed. A simple RETURN is no longer treated as a null string. It is just ignored. Another feature we can use; no more tests for null inputs — they simply can't happen with this program structure. And so we have RETURN = "ignored" or RETURN = "null" by including or deleting a single semicolon after the prompting message. Very handy.
Let's add lines 40-60 and change 70 to complete our test program for INPUT#. Now it will accept only numeric inputs. The full test program is:
10 OPEN 1,0 20 PRINT "ENTER DATA ?"; 30 INPUT#1, A$: PRINT 40 IF A$="0" THEN 60 50 IF VAL(A$)=0 THEN 20 60 B=VAL(A$) 70 PRINT A$;B 80 FOR J = l TO 1500: NEXT J 90 GOTO 20
This structure rejects non-numeric inputs and (because of the semicolon in line 20) will not accept null inputs.
If you want a simple RETURN to be accepted as a zero, delete the semicolon in line 20 and change line 40 to read:
40 IF A$="0" OR A$="" THEN 60
So we have solved our problem quite nicely for inputs and come up with several very useful options in the process.
Let's make a general observation on the lack of built-in prompting with INPUT#. Neither the double question mark requesting additional inputs nor the "extra ignored" warning is printed. This suggests that you should keep the structure of your input commands as simple as possible, because the operator will not get the usual warnings when he enters incorrect data patterns.
At last, as promised, here is the one-line, noaccidental-exit, solution to the long-standing input problem.
10 OPEN1,0 : PRINT"PROMPT ? ";:INPUT #1,A$ : PRINT : CLOSE 1
Obviously, the OPEN and CLOSE commands could span a group of inputs or even the entire program. You can safely leave the "file" open while doing other things.
As a bonus, you can accept null inputs by deleting the semicolon in the first print command. This allows you to convert the nulls to zeros for numeric applications.
Finally, I think you will find it interesting to watch your experienced friends try to terminate a program which uses the INPUT# technique. They tend to get very frustrated, which suggests that maybe you shouldn't build escape-proof programs unless they are really needed.