The QBasic Forum      Other Subforums, Links and Downloads
  << Previous Topic | Next Topic >>Return to Index  

Some debugging techniques

March 23 2008 at 9:44 PM
  (Premier Login iorr5t)
Forum Owner

A program is required that generates 5 random numbers in the range 0 to 49. The numbers should be unique and displayed in order such as 3 8 12 33 46

Then the total of the generate numbers should be displayed.

Here is the program showing the power of CONST to debug.
It is designed to create 3 numbers rather than 5
It is designed for a max of 4

Why? Because the likelyhood of getting a duplicate
is so low for 5 numbers in the range 0-49 that you
can't test that case. This means someday your program
will go down a path that was not tested. BAD. With the
new values, it is surely tested.

Run it like this:
Either compile and run the EXE, or from the DOS prompt
START QBASIC / RUN Z
(where you have Z.BAS in NOTEPAD (ASCII) format.

Keep pressing ENTER until yo are satisfied. Voilà,
your program is debugged. You can play around with
other values to see what happens for bigger values.
Change the CONSTs for 20 numbers in the range < 22.

To stop the program, don't just press Enter, but
instead enter something such as "q".

Anyway, to meet your original specification you just
have to change the CONSTs to
CONST maxCNT = 5
CONST maxN = 50

and be confident that if 32 were generated twice by
RND, no problem - your program will handle it.

Mac

CLS
RANDOMIZE TIMER

CONST maxCNT = 200: ' Don't hard code 5's
CONST maxN = 201: ' Don't hard code 50

DIM N AS INTEGER ' A candidate integer
DIM l(maxCNT) AS INTEGER ' Accepted candidates
DIM cnt AS INTEGER ' Count of accepted candidates
DIM dup AS INTEGER ' 0=No -1=Yes
DIM i AS INTEGER, j AS INTEGER ' Work variables

' ### Generate the numbers
DO
  dup = 0
  N = INT(RND * maxN)
  FOR i = 1 TO cnt
    IF N = l(i) THEN dup = -1: EXIT FOR
  NEXT i
  IF NOT dup THEN cnt = cnt + 1: l(i) = N
LOOP WHILE cnt < maxCNT

' ### Sort them
FOR i = 1 TO maxCNT - 1
  FOR j = i + 1 TO maxCNT
    IF l(i) > l(j) THEN SWAP l(i), l(j)
  NEXT j
NEXT i

' ### Compute total while printing entries
DIM Total AS INTEGER
FOR i = 1 TO maxCNT
  PRINT l(i);
  Total = Total + l(i)
NEXT i
PRINT : PRINT : PRINT : PRINT "Total is"; Total

' Exit the program
LOCATE 25, 5
LINE INPUT "Enter nothing to run again, something like 'q' to exit: "; e$
IF e$ = "" THEN RUN
CLS
SYSTEM

' Problem courtesy of
' http://www.petesqbsite.com/forum/viewtopic.php?t=2629


    
This message has been edited by iorr5t on Mar 23, 2008 11:20 PM


 
 Respond to this message   
AuthorReply

(Login MCalkins)
R

Re: Some debugging techniques

March 23 2008, 10:19 PM 

>Why? Because the likelyhood of getting a duplicate
is so low for 5 numbers in the range 0-49 that you
can't test that case. This means someday your program
will go down a path that was not tested. BAD. With the
new values, it is surely tested.

You can test it...
To do so without interrupting the program in the interpretor, you could replace
N = INT(RND * maxN)
with:
print cnt
input N
and enter a duplicate number, and see that cnt hasn't changed.
Easier still would be to interrupt the program in the QBASIC interpretor. after executing
N = INT(RND * maxN)
once, comment it out and step through it with F8 to see that N = l(i) is considered true, and cnt isn't being incremented. This exploits the power of the interpretor, which is QBASIC's strongest advantage over other languages, IMO.

>DIM l(maxCNT) AS INTEGER

This creates 1 more element than necessary. You could specify an lbound of 1, but it would be much better to specify a ubound of maxCNT - 1. If the latter option were taken, adjustments would need to be made, including putting l(i) = N before cnt = cnt + 1.

>FOR j = i TO maxCNT

shouldn't that be:
FOR j = i + 1 TO maxCNT

However, using CONSTs is a good idea for constants that may need to be adjusted. You only have to change 1 line instead of hunting through the whole program.

I also like the way you coded the part to generate the numbers. It seems a little better than what I would have probably written.

Regards,
Michael


    
This message has been edited by MCalkins on Mar 23, 2008 10:21 PM


 
 Respond to this message   

(Premier Login iorr5t)
Forum Owner

Good Observations, Michael

March 24 2008, 12:06 AM 

> To do so without interrupting the program in the
> interpretor, you could replace
> To N = INT(RND * maxN)
> To with:
> To print cnt
> input N
> and enter a duplicate number, and see that cnt
> hasn't changed.

> Easier still would be to interrupt the program in the
> QBASIC interpretor. After executing
> N = INT(RND * maxN)
> once, comment it out and step through it with F8 to see
> that N = l(i) is considered true, and cnt isn't
> being incremented. This exploits the power of the
> interpretor, which is QBASIC's strongest advantage
> over other languages, IMO.

GOOD! The point being that the programmer has many options and should not get stuck on one way to debug. The main point of this thread is simply "there is at least one way to certify this program as totally debugged for all cases". Don't distribute bug prone code.



> DIM l(maxCNT) AS INTEGER

> This creates 1 more element than necessary. You could
> specify an lbound of 1, but it would be much better to
> specify a ubound of maxCNT - 1. If the latter option
> were taken, adjustments would need to be made,
> including putting l(i) = N before cnt = cnt + 1.

I generally just waste the element. It is very rare
that you run across the case that you need zero. I should, however, have coded
     DIM l(1 to maxCNT) AS INTEGER
so that an element is not accidentally placed in l(0)


> FOR j = i TO maxCNT

> shouldn't that be:
> FOR j = i + 1 TO maxCNT

RIGHT!  In fact, so right that I edited the program and changed
        that line. Couldn't stand it.



>  However, using CONSTs is a good idea for constants
>  that may need to be adjusted. You only have to
>  change 1 line instead of hunting through the whole
>  program.

YES
In fact I will go so far as to say "Never hard code when you can avoid it!"

Except for special cases of zero and one. These can safely be hard coded.

  for i = 1 to max
is natural looking
  for i = One to max
looks strange.

Well, books can be written and I have posted a lot of advice such as Advanced Design and Modular Debugging Techniques
http://www.network54.com/Forum/178387/message/1069000429/

Mac


    
This message has been edited by iorr5t on Mar 24, 2008 12:13 AM
This message has been edited by iorr5t on Mar 24, 2008 12:12 AM
This message has been edited by iorr5t on Mar 24, 2008 12:10 AM


 
 Respond to this message   
qbguy
(no login)

Yes, CONST is very useful

March 24 2008, 3:02 PM 

CONST lets you give names to constants; instead of referring to pi as 3.14159265358979323846264338327950288419716939937510 at every appearance, the variable PI can be given that value with a CONST statement and used instead of the longer form of the constant. This also simplifies modifying the program, should the value of pi change.

Of course, the stupid way to use CONST is:

CONST ONE = 1
CONST TWO = 2
CONST THREE = 3

Or even worse:

CONST THOUSAND = 42


----
A computer without COBOL is like a piece of chocolate cake without ketchup.

 
 Respond to this message   

(Login burger2227)
R

* Try Pi = 4 * ATN(1#) . Why would you really need any more accuary in QB?

March 28 2008, 8:28 PM 



    
This message has been edited by iorr5t on Mar 30, 2008 3:34 AM
This message has been edited by burger2227 on Mar 28, 2008 8:58 PM


 
 Respond to this message   
Asterisk Police
(no login)

* If there is an asterisk, then why is there stuff in your post?

March 29 2008, 4:08 PM 


 
 Respond to this message   

(no login)

*Reminds me of infinite state machines, and the problems there-in, very interesting Mac

April 5 2008, 6:42 AM 

*

 
 Respond to this message   
Current Topic - Some debugging techniques
  << Previous Topic | Next Topic >>Return to Index  

Newbies usually go to www.qbasic.com and click on The QBasic Forum
Forum regulars have their own ways, which include The QBasic Community Forums