********************************************************************* This article is being presented through the *StarBoard* Journal of the FlagShip/StarShip, SIGS (Special Interest Groups) on the Delphi and GEnie telecommunications networks. Permission is hereby granted to non-profit organizations only to reprint this article or pass it along electronically as long as proper credit is given to both the author and the *StarBoard* Journal. ********************************************************************* Learn BASIC by Debugging by Tim Sickbert (MIDNIT on DELPHI) Learning BASIC can be intimidating. It doesn't matter how long you have had your computer, or how well you can process words, numbers, or names. Nor does it matter how many programs you have keyed in from magazine listings and "Learning BASIC" books. You may still not feel comfortable with BASIC. I got my computer about a year ago, primarily as a word processor, but also to learn a bit about programming. After six months, I had typed in about twenty or so programs from the manuals and from magazines, and I still felt that I didn't know a fool thing about how to write a program. Oh, I had written a few cute little things to make the screen change color and to print things out, but nothing that DID anything. The biggest problem I had was thinking of something to write a program for. All these cute little things did not add up to much, and I could see no reason to carry them further. It was really rather discouraging. Then, one day in a newsletter I found a short little listing for printing out mail labels. It was really pretty easy, and I never would have thought of doing the same thing myself. But I was bored, so I read the article that came with the listing, and typed it in. It turned out that I had learned something over the months. I had a good idea about how a program should be written, and I had a strong feeling about how the BASIC commands should be used. Everything I had learned added up to tell me that the program I was looking at needed a good little bit of work. INSPIRATION!!! I didn't need to come up with my own ideas for a program (I am not that creative) - I could take somebody else's idea, find its flaws (there is no such thing as a perfect piece of code), make it work better, and add my own bells and whistles. Every time I had come up with an idea of my own, I had figured, "Naw, that wouldn't be a REAL program...it would just be a few lines to make it look like I was programming." Working on somebody else's program somehow made it more legitimate for me. The point of all this is that you can learn programming by taking somebody else's BASIC program, finding its flaws, and adding to the program to make it do more, and do it better. You probably won't want a program out of a magazine as they can get rather long and tedious. Probably the best thing to work on is a short routine that a moderate-level programmer would sit down and type in as a quickie, just to serve his immediate need. Many programmers will sit down and need to get something done pretty quick. Rather than write a fully developed program, they get down and dirty - they patch and kludge. If a programmer had a need for it, so does somebody else. The original version won't do because it was probably written pretty carelessly, and probably doesn't do much in the first place. But if you take that idea, clean it up, and expand it, you may be able to make a decent little utility out of it. I had a check bounce last fall, and was rather anxious to find out where I had made a mistake in balancing my checkbook. The batteries in my calculator were dead. I didn't have the patience to learn how to use a spreadsheet right then, and I REALLY didn't want to do it on paper. I typed in a quickie little program that looked a lot like this: 10 b$="" 20 a$="" 30 get a$:ifa$=""then80 40 if val(a$)>0 and val(a$)<9 then b$=b$+a$:printa$;:goto77 50 if a$="0" then b$=b$+a$:goto77 60 if a$="+" then b=val(b$):tt=tt+b:print,tt:goto75 70 if a$="-" then b=val(b$):tt=tt-b:print,tt:goto75 80 if a$="*" then b=val(b$):tt=tt*b:print,tt:goto75 90 if a$="/" then b=val(b$):tt=tt/b:print,tt:goto75 Pretty cheesy, eh? Well, it took me almost half an hour to write that and get it working the first time. I found the mistake in my checkbook, so I was happy. But it was not the kind of thing I would show off to my friends; it is rather lacking in features and elegance. I knew right away that it was a handy little thing, though, and that I would want to use it again sometime, the next time the batteries in my calculator died. So why not make it work a bit better? Add a few more features? Maybe make some kind of article out of it? Anyway, that little program is what I started out with. Look at it, type it in, run it. Not so hot, but it is a start. What problems does it have? To begin with, there is no cursor, no error checking, and no way to tell what is going on. But there IS an idea. I had started something. So, the first thing, of course, is to figure out what all would be nice in a progrm like this. Instructions are always nice - put in some REM statements to remind myself what I am doing; print messages to the screen so users, including me, know what the program was doing; and generally make the program prettier. In fact, when I expanded this program, the first thing I did was write the instructions and a blank program. In the instructions (VERY much edited since the original writing) I PRINTed everything I wanted the program to do. Then I entered a whole bunch of empty lines - line numbers with just a colon - with a REM statement at every even hundred line number (100, 200, ..., etc.) that told what routine I would put there. That gave me something of a structure, some idea of where I was going, and all I had to do was write the little routines. It helped me, anyway. I suggest that, if interested, you try to do the same kind of thing right now, before continuing with this article. Take the program above, or another little one that you have sitting around, figure out what it needs to make it useful, write the instructions, and set up the lines that you can fill in with routines. This can get you started programming. The rest of this article will be about the above program in its present state, as found in the listing at the end of this article. The program is still not fully developed, but is an example of a somewhat later stage. You should have the listing for the Simple Adding Machine before you as you look at this. It looks kind of convoluted. It doesn't really need to be, but there is a reason for it. As I was writing the program, it looked a whole lot different. Lines 1260 to the end of the program were at the very beginning; lines 1130 through 1240 followed right after that. Having the REMs and the setup part of the program at the beginning is how you usually see it. Well, the last thing I did was move these to the end because they take up space (and therefore time) if they are at the beginning of the program. This program spends most of its time GETting characters and going through loops and GOing TO. This can take a lot of time, especially on the C128 in SLOW mode. So I tried to put all the really busy parts of the program at the beginning. Outside of that, the REMarks pretty much document the structure of the rest of the program. The program flows pretty simply from the input routine, through the evaluation and printing of the character got, to the adding of the entries and totals to an array. The individual routines deserve some bit of attention as well. The first routine is a simple flashing cursor routine that does little more than show the user where an entry will go and wait for a key to be pressed. The actual routine is the four lines from 200 through 230, inclusive. The counter, 'ct', determines how fast the cursor blinks. The variable 'fl' determines whether the pseudo cursor (the space character, alternately normal and reversed), will be the background or the character color, to give it its flash. The next routine starts the evaluation of a character once it has been entered. Rather than use string literals, I decided to use the ASC() value of the CHR$(). I did that for two reasons. The first was to trap all the numeric characters which have an ASCII value ranging from 48 to 57. The test in the original program used the VAL() function, which was ok; but I had to use another line to test for the zero character becuase any non-numeric character returns a zero from the VAL() function. Note that in using the ASC() function, it is necessary on most Commodore machines to add a CHR$(0) to the string for it to work. A lot of lines in this and the next routine trap special characters such as line 20 (which allows you to use the minus sign for negative numbers), line 310 (which provides for the key), and other special characters. The next routine takes the characters that filtered through the above routine, traps the comma and the decimal point, and evaluates the function. Lines 480 and 500 are leftovers - the characters should have been trapped earlier. The storage feature is one of those not fully developed. Such a feature could come in handy when you are balancing a checkbook, and keep finding a mistake. What it needs is a print feature that would provide a hardcopy so you could compare it more easily to the actual entries in your checkbook. I leave that to you. Only two other routines deserve attention. The SEQ file print routine in lines 640-760 that provides for single and dual disk drives with any legal device number. The setup routine checks to see if the computer is a C64 or a C128. These are the two most Commodore computers right now, but lines 1150-1200 can be deleted or REMed out for other machines. The program is generic Commodore BASIC 2.0 and should run unaltered on any Commodore 65xx system, with the exception of those 6 lines. The program itself is no great shakes, but the idea of taking a simple program and debugging and expanding it can get you started in BASIC programming. Look for the little routines in newsletters, magazines, etc., and see what you can do with them. Stay away from the big, convoluted programs until you have had some practice, but then see what you can do with those as well. [Copyright 1986, Timothy B. Sickbert. Permission granted to non-profit groups to reprint all or part of the article, or to pass it on via electronically coded files, provided credit is given the author. Please address questions, comments, or what have you, to Tim Sickbert, P.O. Box 1747, Champaign, IL 61820, or on Delphi to MIDNIT, on Quantum Link to The Paper.] ********************************************************************* SIMPLE ADDING MACHINE (program listing) 100 goto920 110 rem "Notes and Credits at End of Program 120 : 130 rem "Start adding machine program here 140 : 150 rem "Simple flashing cursor input 160 : 170 tt=0 180 fl=1:b$="" 190 a$="" 200 get a$:if a$<>""then270 210 ct=ct+1: if ct<>10 then goto200 220 ct=0: fl=-fl:if fl=-1 then print " ";:goto200 230 print " ";:goto200 240 : 250 :rem "A key has been hit. Evaluate 260 : 270 a=asc(a$+chr$(0)) 280 if a>47 and a<58 then b$=b$+a$:printa$;:goto190 290 if (len(b$))=0 and a$="-" then b$=a$:printa$;:goto190 300 if a>41 and a<48 then 410 310 if len(b$)>0 and a=20 then print a$;:b$=left$(b$,(len(b$)-1)):goto190 320 rem above line deletes 330 if a = 94 then b=val(b$):tt=ttE}Ab:print"E}A";tab(8)tt:goto550 340 if a = 13 then a$="+":a=43:goto430 350 if a = 195 then tt=0: print"Clear"tab(8)tt:goto550: rem " Shift C = clear 360 if a = 209 then 600: rem "Shifted Q 370 goto190 380 : 390 : rem "Evaluate chr$( codes range 42-47 400 : 410 if a = 44 then 180 : rem comma 420 if a=46 then b$=b$+a$:printa$;:goto190: rem "DECIMAL POINT 430 print a$;: b=val(b$):print tab(8);: 440 on 48-a goto 510,500,490,480,470,460 450 rem "Multiply, Add, Comma, Subtract, Decimal, Divide 460 tt=tt*b:printtt:goto550 470 tt=tt+b:printtt:goto550 480 print "This line should never execute!!! COMMA":stop 490 tt=tt-b:printtt:goto550 500 print"This line should never execute!! DECIMAL POINT":stop 510 tt=tt/b:printtt:goto550 520 : 530 : rem "If storing, add to array 540 : 550 if aa=0 then goto 180 560 a1$(tc)=b$+a$:a2(tc)=tt:tc=tc+1:goto180 570 : 580 rem" Quit and close 590 : 600 input "Quit. Are you sure? y";rs$ 610 if rs$<>"y"then 550 620 if aa=0 then end 630 input"Do you want to save the arrayed data in a sequential disk file? n";rs$ 640 if rs$<>"y" then end 650 input"Sequential file name ";fi$ 660 input"Disk device number 8";de$:de=val(de$):if de<1 or de>30 then 660 670 input"Drive number 0";dr$:dr=val(dr$):ifdr<0ordr>1 then 670 680 print"Any key to continue with disk file print": 690 getrs$:ifrs$=""then690 700 close15:open15,de,15:gosub 840 710 open2,de,2,""+dr$+":"+fi$+",s,w":gosub840 720 for i=0 to tc:print#2,a1$(i),a2(i):next 730 gosub 840 740 print#2:close2 750 input#15,e1,e1$,et,es:print e1,e1$,et,es 760 close1 770 input"quit , clear , or continue c";rs$ 780 if rs$="u" then goto 180 790 if rs$="c" then tt=0:tc=0:print"Clear"tab(8)tt:goto170 800 end 810 : 820 : rem "Disk access error checking routine 830 : 840 input#15,e1,e1$,et,es 850 if e1<20 then return 860 printe1,e1$,et,es:close2:close15 870 print"Disk output aborted": goto 770 880 : 890 : 900 rem "Instructions, notes, etc 910 : 920 printchr$(147)chr$(14) 930 print" This program functions as a small 940 print" adding machine. It will properly 950 print" handle all mathematical operators, and 960 print" it provides an option for storing your 970 print" entries and running totals in an array 980 print" which may be saved as a sequential 990 print" file for later reference. 1000 print" The program is still a little bit 1010 print" thin. Other features you can add 1020 print" might fill the array from a sequential 1030 print" or print a hardcopy of entries and 1040 print" totals to a printer. 1050 print" This program will ignore keys other 1060 print" than the number keys, the numerical 1070 print" function keys, the 'c' (to 1080 print" clear the running total), and the 1090 print" 'q' (to quit). 1100 print" Any Key to Continue 1110 geta$:ifa$=""then1110 1120 : 1130 rem "Setup 1140 : 1150 sy=0:if peek(65280) then sy=1:rem"sy=0 - C128; sy=1 - c64 1160 if sy=1thenpoke808,234:rem" disable 1170 if sy=0 then input" Do you want to use C128 FAST mode y";rs$ 1180 if rs$="y" then fast 1190 if sy=0 then key 1,"*":key3,"/":key5,"E}A" 1200 if sy=0 then print "F1=*, F3=/, F5=E}A" 1210 print" Do you want to store your" 1220 input" entries and totals in arrays n";rs$ 1230 if rs$="y" then aa=1:input" How many elements for storage";a1%:dim a1$(a1%),a2(a1%):tc=1 1240 goto170 1250 : 1260 rem *************************** 1270 : 1280 rem " Simple adding machine 1290 : 1300 rem " Tim Sickbert 1310 rem " June 1986 1320 : 1330 rem *************************** 1340 : 1350 rem" This program is written to accompany 1360 rem" an article on learning BASIC by 1370 rem" taking a simple BASIC program, 1380 rem" debugging it, trimming it down, and 1390 rem" adding features to it. You are 1400 rem" invited to do the same with this one. 1410 : 1420 rem" If you have any questions, comments, 1430 rem" or criticisms - or if you find any 1440 rem" glaring examples of bad programming - 1450 rem" please let me know. 1460 rem" Send E-mail to: 1470 rem" on Delphi - MIDNIT 1480 rem" on QLink - The Paper