QBasic - Common Programming Errors

HomePage | Optical Illusions | War Stories | QBasic | Dads Navy Days | Bristol | Bristol, USA | Bristol, Canada | Terre Haute | Miscellany | Web Stuff | About Ray | Site Map | Site Search | Messages | Credits | Links | Web Rings

QBasic | Errors | 40lb Weight | Bits | Chance | Colours | Dates | Delays | File Dialog | Files | Input | Matching | Menus | Mouse | Numbers | SeqNo | SIRDS | Sorts | Text | Timer | DLoads

Programming Errors:

Everybody makes mistakes when programming, from simple "oops, typed that wrong." or "oh yeah, forgot the syntax for that." to "What the hell's going on in there?"

Errors are almost inevitable, and fall into one of three main camps :-

Example 1

A little while ago I wanted to test some sort algorithms. The code I wanted to test came with some sample data but was a bit limited having only 40 odd variables. I wanted to test them using something more akin to a real world test. I wrote a program that produced some files, one completely sorted but 'upsidedown', two nearly sorted but with with some numbers transposed and one completely random.

The first couple was fine but the completely random one didn't work at all well. My original logic for this piece of code was this :-

Generate a random number between 1 and 30,000

Check this number wasn't already in an array

If it was not already present put this number into the array and write it to disk

If it was already present generate another random number and check again

Continue the above until the numbers 1 to 30,000 were generated in a random order.

The actual code to accomplish this was :

   	RANDOMIZE TIMER	
	For Count = 1 to 30000
 	   DO
	      Number = (RND * 30000) + 1
 	      FOR Counter = 1 TO Count 
 	         IF Number = NumArray(Counter) THEN EXIT FOR 
    	      NEXT Counter 
 	   LOOP UNTIL Counter = Count + 1 
 	   NumArray(Count) = Number 
 	   Print #1, NumArray(Counter)
 	Next Count

Nothing much wrong with that - at first glance. It starts quite quickly - the array starts off quite small but as more numbers are generated it has to do more and more checking. Not only that but with less choice in the number of random numbers that can be made before it meets a match this program starts to run very very slowly. In fact, after 26 hours it still had only generated 28,000 different numbers and I had to stop the program and have a rethink.

I changed the logic slightly so that :-

Create an array that contains the numbers 1 to 30,000 in order

Generate a random number between 1 and the length of the array (initially 30,000)

Take that array element and write it to a file

From the number generated to the end of the array shuffle the numbers upwards by one

Decrease the range of the random number by one (at each step through the loop)

Continue until all 30,000 elements of the array have been written to disk

The code now becomes :-

	'Make an array of completely sorted numbers
	FOR Count = 1 TO 30000
           NumArray(Count) = Count
	NEXT Count
	RANDOMIZE TIMER
	FOR COUNT = 1 TO 30000
	   Number = (RND * (30001 - Count)) + 1
           PRINT #1, NumArray(Number)
           FOR Counter = Number TO 30000 - Count
                NumArray(Counter) = NumArray(Counter + 1)
           NEXT Counter
	NEXT COUNT

This code starts off quickly and gets faster as the array gets smaller. A few minutes later I had 30,000 randomly generated numbers in the range 1 - 30,000. A vast improvement of having to wait for over 26 hours when it didn't even finish.

User Errors:

As well as the programming errors, a programmer should also think of errors that a user might make. In short, to make his programs bullet-proof. A user may type a file name for an output file, do they know that a file of the same name may already exist? Do they want to overwrite it or be given the chance to choose a new file name? If you've asked a user to input something, what happens if they've given you a number larger than 32,676 and you've only provided enough storage for an integer. What happens if your program expects a number and they type in a character or vica versa?

I've called this chapter User Errors, this a mistake, errors of this sort should be anticipated and allowed for by the programmer.

The following program, FileErr.bas, tests whether a file (C:\rayray.ray) exists, if it does not then it creates it, then tests for it again. The file is deleted on exiting the program.

'FileErr     Ray Thomas      May 2000

'A program to demonstrate how to test if a file exists

OutFile = FREEFILE
ON ERROR GOTO Err1
CLS
PRINT

OPEN "C:\rayray.ray" FOR INPUT ACCESS READ LOCK READ WRITE AS OutFile
CLOSE

'If, by some fluke, the file already exists I'm leaving
'******************************************************
PRINT "The file C:\rayray.ray already exists, exiting program"
END

NoFile1: '*** Return to here after the initial error report ***
PRINT
PRINT "Press any key to create it ..."
PRINT

DO
LOOP UNTIL INKEY$ <> ""

OPEN "C:\rayray.ray" FOR OUTPUT ACCESS WRITE LOCK READ WRITE AS OutFile
PRINT #OutFile, "This file is for test purposes only"
PRINT #OutFile, "and can be safely deleted."
CLOSE

PRINT
PRINT "The file now exists ..."
PRINT
PRINT "Press any key to check that it does !"
PRINT
PRINT

DO
LOOP UNTIL INKEY$ <> ""

ON ERROR GOTO Err2
OPEN "C:\rayray.ray" FOR INPUT ACCESS READ LOCK READ WRITE AS OutFile
CLOSE
PRINT "The file we've written, does indeed exist,"
PRINT "If it didn't then this message wouldn't show !"
PRINT "It is here that the user can be asked whether they want to change"
PRINT "a file name, overwrite one, exit the program or whatever."
PRINT
PRINT
PRINT "Press any key to delete C:\rayray.ray and end the program ..."

DO
LOOP UNTIL INKEY$ <> ""

KILL "C:\rayray.ray"

END

Err1:
IF ERR = 53 THEN
        PRINT
        PRINT "It's OK to create C:\rayray.ray, it does not already exist."
        PRINT "We know this because the error code returned was"; ERR
        RESUME NoFile1:
END IF

Err2:
IF ERR = 53 THEN
        PRINT
        PRINT "mmm, something wrong here, we just wrote the file"
        PRINT "and so we shouldn't see this message !"
        PRINT "The error code returned was"; ERR
        PRINT
        PRINT "Exiting program ..."
        END
END IF

Notice that the program only tests for Error 53 - File not found. The ON ERROR GOTO routine can take care of any of the 76 run time errors that can stop a program from working, in the example above the returned error code can give information back to the program.

Pebe wrote a nice little 6 line piece of code that will does a similar thing but in a different way :-

SUB check4file(filename,a%)  
OPEN (filename) FOR APPEND AS #1  
IF LOF(1)=0 THEN a%=0 ELSE a%=1  
CLOSE filename
IF a%=0 THEN KILL (filename)  
END SUB

When I was writing this I tried with other types of error codes, especially those of variable overflow, Error 6. QBasic has it's own handler for this, the rather inelegant "redo from start" message, which if you've gone to the trouble of designing a nice screen, is certainly going to mess it up for you.

To see what I mean use this program snippet :-

DIM Num AS INTEGER

CLS
PRINT
ON ERROR GOTO InErr
INPUT ; "Type in a number bigger than 32,767 (or a letter)   " , Num
END

InErr:
PRINT
PRINT "Bet you never get to see this message."
RESUME NEXT

A way round this problem is to dump INPUT or INPUT$ altogether and write your own verification code, trapping key presses, by using INKEY$ instead. I've written one that you can adapt, it can be found in Input.

QBasic | Errors | 40lb Weight | Bits | Chance | Colours | Dates | Delays | File Dialog | Files | Input | Matching | Menus | Mouse | Numbers | SeqNo | SIRDS | Sorts | Text | Timer | DLoads

HomePage | Optical Illusions | War Stories | QBasic | Dads Navy Days | Bristol | Bristol, USA | Bristol, Canada | Terre Haute | Miscellany | Web Stuff | About Ray | Site Map | Site Search | Messages | Credits | Links | Web Rings


GoStats stats counter