home *** CD-ROM | disk | FTP | other *** search
/ 8bitfiles.net/archives / archives.tar / archives / genie-commodore-file-library / Information / BEGIN-BASIC-WITH-BUGS < prev    next >
Encoding:
Text File  |  2019-04-13  |  18.4 KB  |  403 lines

  1. *********************************************************************
  2. This article is being presented through the *StarBoard* Journal of
  3. the FlagShip/StarShip, SIGS (Special Interest Groups) on the
  4. Delphi and GEnie telecommunications networks.  Permission is
  5. hereby granted to non-profit organizations only to reprint this
  6. article or pass it along electronically as long as proper credit
  7. is given to both the author (when known) and the *StarBoard* Journal.
  8. *********************************************************************
  9.  
  10.  
  11.  
  12. BEGIN BASIC WITH BUGS
  13.  
  14. by Tim Sickbert (MIDNIT)
  15.  
  16.  
  17.  
  18. [This article is Copyrighted 1986, by Timothy B. Sickbert. The article
  19. and accompanying program first appeared in the April 1986
  20. Champaign-Urbana Commodore User's Group Newsletter. Permission is
  21. hereby granted to non-profit organizations to re-print this article, to
  22. pass it along electronically, provided credit is given the author, or
  23. to throw it away, as long as the author is not mentioned. Permission is
  24. also granted to commercial electronic information services to include
  25. this article among the files which users may freely download, provided
  26. credit is given the author. Comments are invited. Please address to the
  27. Timothy B. Sickbert, P.O. Box 1747, Champaign, IL 61820.]
  28.  
  29.      One of the best ways to learn to program, aside from writing your
  30. own programs, is to take a program written by somebody else, debug, and
  31. rewrite it. So, to help get you started with BASIC, I am going to write
  32. an ongoing column on BASIC debugging.
  33.  
  34.      What I will do is give, in this and future columns, a listing of a
  35. BASIC program that is poorly written. It will have flaws in the overall
  36. design and the actual code. Some of the flaws will be obvious; some
  37. more subtle. I will try to have to different programs in each issue of
  38. the newsletter. The corrections for one of the programs will be
  39. included and the corrections for the other program will appear the
  40. following month. So, to start things off...
  41.  
  42.      The following article and program appeared some time ago in a
  43. Commodore User's Group newsletter. It is supposed to be a nice, simple,
  44. little utility for printing multiple mail labels with the same name and
  45. address, such as you could use for return address labels. The program
  46. is poorly designed and coded, having both major and minor errors. For
  47. this first program, I will comment on the problems and how to fix them.
  48. I will give you another program to work on yourself and then comment on
  49. that second program next month and give my revision. I will also give
  50. you another buggy program next month.
  51.  
  52.      Revised code, showing better use of BASIC, appears later in this
  53. issue. But before you look at the revisions, see if you can find the
  54. problems with this version of the program.
  55.  
  56.          Often, I have wanted to make my own address labels. I have
  57.     several programs for mailing lists, but I wanted quantities of one
  58.     specific label and none of my programs would do this.
  59.          I finally decided to write my own program and was surprised at
  60.     how simple it was.
  61.          I have not dressed up the program, except for the FOR/NEXT
  62.     loop and to make it for double wide labels.
  63.          In the form presented, it will print labels two across. If you
  64.     want single wide labels, simply omit the semi-colon (;) in all the
  65.     even thousand lines (1000, 2000,...) and omit the next line after
  66.     the semi-colon (1100,2100,...).
  67.          Line 200 sets the quantity of labels. It is currently set at
  68.     20 for double wide (10 x 2 across) or 10 for single wide.
  69.          Simply change the data in quotation marks to your data and run
  70.     the program.
  71.          I used a Commodore MPS 801 printer. I am not familiar with
  72.     others but assume that they will work the same. I originally
  73.     intended to add to the program, but have decided to let you alter
  74.     the program as you see fit.
  75.  
  76.          100 OPEN 4,4
  77.          200 FOR X = 1 TO 10
  78.          1000 PRINT#4,"NAME";
  79.          1100 PRINT#4,TAB(40)"NAME"
  80.          2000 PRINT#4,"ADDRESS";
  81.          2100 PRINT#4,TAB(40)"ADDRESS"
  82.          3000 PRINT#4,"CITY,TOWN,ZIP"
  83.          3100 PRINT#4,TAB(40)"CITY,TOWN,ZIP"
  84.          4000 PRINT#4,;
  85.          4100 PRINT#4,
  86.          5000 PRINT#4,"TELEPHONE"
  87.          5100 PRINT#4,TAB40"TELEPHONE"
  88.          6000 PRINT#4
  89.          6100 PRINT#4,
  90.          9000 NEXT
  91.          9500 CLOSE4
  92.          10000 END
  93.  
  94.  
  95.  
  96.  
  97.      Don't look at this until you have tried to find the flaws in the
  98. mail label program listed with the first half of this article.
  99.  
  100.  
  101.  
  102.      First, we must give the original author credit for his disclaimer.
  103. He says that the program is not dressed up and that he is not too
  104. familiar with printers other than the MPS 801. He is really inviting us
  105. to do what we are doing here: Taking a simple design and expanding it.
  106.  
  107.      Still, the original program shows a poor understanding of BASIC in
  108. general, and of printers and printer commands in particular. A printer
  109. is not the same thing as a video display screen and must be treated
  110. differently from BASIC.
  111.  
  112.      The first mistake is in using the TAB command to space over to the
  113. second set of labels. The TAB command does not work correctly with many
  114. printers. It will often tab from the current position the print head,
  115. rather from the left margin or leftmost column - if it works with your
  116. printer at all. In fact, the Commodore 128 System Guide states that,
  117. "The TAB function can only be used with the PRINT statement, since it
  118. has no effect if used with the PRINT# to a logical file." Well, it
  119. happened to work for the author with his MPS 801. It will not work on
  120. most printers.
  121.  
  122.      The second error appears in lines 4000-4100 and 6000-6100.
  123. Actually, this is not so much a coding error as a style error. The
  124. author is bending the code to fit the documentation - the author says
  125. to delete lines for single wide labels. Well, it does work. But it
  126. could have been better handled. In the actual coding, these sets of two
  127. lines each provide a single line feed, i.e., the printer rolls the
  128. paper up one line. There is no need for lines 4100 or 6100 except to
  129. match the documentation.
  130.  
  131.      The third major error is in line 9500. The author closes the
  132. communications channel to the printer without first unlistening it.
  133. "Unlistening" means to tell the printer not to expect any more data,
  134. and is done by sending a "PRINT#4," without any other data, immediately
  135. before closing the channel. The author comes very close to accidental
  136. elegance - like doing a swan dive when falling off a bridge - in line
  137. 6100. There he has a "PRINT#4," statement. This might succeed in
  138. unlistening the printer if he had not put the comma at the end of the
  139. command.
  140.  
  141.      The final, minor, error, is in designing a program for double wide
  142. labels. If any of you have double wide labels, let me know; I have
  143. never seen them. Oh, sure, they are available. But they are rare. If
  144. anybody is going to bother looking for double wides, let THEM modify
  145. the program - they are in the minority. The author of the program
  146. apparently does not know much about users, or does not care much about
  147. making the program useful and easy to the majority of users. But, to
  148. show how to handle formatting simple printed output, I provided for
  149. double wide labels in my revisions.
  150.  
  151.      So, one example of amended code looks something like this:
  152.  
  153.           10 REM
  154.           20 REM  CHAMPAIGN-URBANA COMMODORE USERS GROUP
  155.           30 REM               APRIL 1986
  156.           40 REM          TIMOTHY B. SICKBERT
  157.           50 REM
  158.           100 CR$=CHR$(13):SP$=CHR$(32):REM CARRIAGE RETURN AND SPACE
  159.           110 DIM NM$(4)
  160.           120 FOR I = 1 TO 4: READ R$: NM$(I) = R$: NEXT
  161.           130 DATA "NAME","ADDRESS","CITY, STATE, ZIP","TELEPHONE"
  162.           140 N=40-LEN(NM$(1)):A=40-LEN(NM$(2)):C=40-LEN(NM$(3)):
  163.              T=40-LEN(NM$(4))
  164.           150 :
  165.           160 OPEN4,4,7
  166.           170 FORX=1TO10
  167.           180 PRINT#4,NM$(1);
  168.           185 FORY=1TON:PRINT#4,SP$;:NEXTY:PRINT#4,NM$(1)
  169.           190 PRINT#4,NM$(2);
  170.           195 FORY=1TOA:PRINT#4,SP$;:NEXTY:PRINT#4,NM$(2)
  171.           200 PRINT#4,NM$(3);
  172.           205 FORY=1TOC:PRINT#4,SP$;:NEXTY:PRINT#4,NM$(3)
  173.           210 PRINT#4,CR$;
  174.           220 PRINT#4,NM$(4);
  175.           225 FORY=1TOT:PRINT#4,SP$;:NEXTY:PRINT#4,NM$(4)
  176.           230 PRINT#4,CR$;
  177.           240 NEXTX
  178.           250 PRINT#4:CLOSE4:END
  179.  
  180.      In line 100 I set up string variables that I will want to use
  181. later, specifically, the ASCII codes for a carriage return and for
  182. space. The need for these will become apparent shortly. Line 110
  183. DIMensions a string array. It is really not necessary to DIMension
  184. arrays of less than 10 elements, but it is often good practice. This
  185. lets somebody else know what you are doing.
  186.  
  187.      The reason I bother to put the name, address, etc., in string
  188. variables is so I can later format the printing more easily. It also
  189. makes the program easier to change for another person to use. Rather
  190. than entering everything twice, for double wide labels, it need be
  191. entered only once - and all in one line, at that.
  192.  
  193.      Line 140 is the key to setting up the double wide format. TAB and
  194. SPC (space) commands do not always work right for formatting on a
  195. printer. But I have to get it to print on the second column of labels.
  196. If I just inserted a certain number of spaces after each item the right
  197. column of labels would be a mess. And since everybody's name is of a
  198. different length, we have to make it handle that, too. So, what I did
  199. was set it up to space over 40 spaces minus the length of the name
  200. (,address, or whatever). Thus the FOR/NEXT loops in the odd numbered
  201. lines from 160 to 250. These loops add however many spaces are needed
  202. to get over to the fortieth column, regardless of the length of the
  203. name and address.
  204.  
  205.      Line 150 is there for one reason only: To separate two distinct
  206. parts of the program. Lines 100 to 140 set up variables; lines 160 to
  207. 250 do the actual printing. I could separated the two with REM
  208. statements, but a colon gives a virtually blank line which makes for a
  209. visual break where REMS can look cluttered.
  210.  
  211.      By using a secondary address of 7 in line 160, I allow the user to
  212. print the labels in lowercase/uppercase. With the implied secondary
  213. address of 0 in the original, the user could use only uppercase. When
  214. using this revision, it is helpful to have the screen in
  215. lowercase/uppercase mode as well. You can get this by
  216. <COMMODORE><SHIFT>.
  217.  
  218.      Line 170 just sets up the number of labels the program will print.
  219.  
  220.      The program is set up for double wide labels. It would have been
  221. alot easier, and probably more useful, to set it up only for single
  222. labels, but I wanted to compare with the original. The even numbered
  223. lines from 180 through 230 are necessary for both single and double
  224. wide labels; the odd numbered lines are needed only for double wide
  225. labels. Setting it up this way causes the same problem as the original:
  226. The user most actually play with the code to change it for single wide
  227. labels. Generally, this should be avoided. If you want to modify the
  228. program for single wide labels, delete the odd numbered lines and
  229. remove the semi-colon from even numbered lines 180 to 200 and 220.
  230.  
  231.      This brings up an interesting little point. In lines 210 and 230,
  232. I have "PRINT#4,CR$;". This looks like an odd little construction. It
  233. is. But this insures that it will work on virtually any printer. I had
  234. defined CR$ as a CHR$(13) in line 100. CHR$(13) is a carriage return
  235. and, for almost all printers, a line feed. Some printers will execute a
  236. carriage return and line feed if you simply "PRINT#4". Others won't. So
  237. sending the CHR$(13) insures that it will feed a line. Other printers,
  238. when sent a CHR$(13), will execute the line feed, and then another for
  239. the command strin! So, we put a semi-colon at the end of the statement
  240. to suppress a possible second line feed. Oh, by the way, the reason we
  241. want extra lines in the first place is because almost all mail labels
  242. are spaced at one inch. Most printers print six lines to an inch. So,
  243. we need to print a total of six lines.
  244.  
  245.      Line 240 closes the loop that started in line 170, and line 250
  246. neatly wraps things up by unlistening the printer, closing the logical
  247. file (communications channel), and ending the program.
  248.  
  249.      The listing above is a decent type-in program. It will run on any
  250. Commodore system straight up; will work with almost any printer; will
  251. handle any name, address, or whatever, less than 40 characters long;
  252. and only one line needs be changed for somebody else to use it. It is a
  253. couple lines longer than the original but it doesn't have the problems.
  254. It would not, however, be a very good program for uploading to a
  255. bulletin board or giving to someone on a disk. It has no documentation
  256. in the listing and never tells the user what is going on. To make it
  257. good for passing around on BBSs or on disks, we should add INPUTs to
  258. get the name, address, etc., and how many copies the user wants. We
  259. should tell the user what is going on by printing messages to the
  260. screen. We should add REM statements to make the listing
  261. self-documenting so somebody else who wants to play with the program
  262. will be able to see what has already been done.
  263.  
  264.      Finally, for real class, we could make it ask the user if he
  265. wanted single or double columns: And make the print routine shorter at
  266. the same time! So, we finally end up with a program that looks like
  267. this:
  268.  
  269.  
  270.       10 rem"******************************
  271.       20 rem"
  272.       30 rem" not so simple label maker
  273.       40 rem"
  274.       50 rem"   Timothy B. Sickbert
  275.       60 rem"
  276.       70 rem"******************************
  277.       80 :
  278.       90 cr$=chr$(13):sp$=chr$(32):rem chr$(13)=carriage return
  279.          chr$(32)=space
  280.       95 rem "qQ][rR" = cursor down, up, right, left, reverse on,
  281.          reverse off
  282.       100 :
  283.       110 print chr$(147);chr$(14):rem
  284.          "clear/home:lowercase/uppercase
  285.       120 print "qqqq]]]]rLabel MakerR":rem cursor down, cursor
  286.          right, reverse on/off
  287.       130 print " I will ask for your full name"
  288.       140 print " street address, apartment #,"
  289.       150 print " city, state, zip code, and "
  290.       160 print " telephone #. Do not use any"
  291.       170 print " punctuation other than a period.qqq"
  292.       180 nm$="":ad$="":ap$="":ci$="":se$="":zi$="":tl$=""
  293.       181 input "What is your full name";nm$
  294.       190 input "What is your street address";ad$
  295.       200 input "What is your apartment #";ap$
  296.       210 input "What is your city";ci$
  297.       220 input "What is your state";se$
  298.       230 input "What is your ZIP code";zi$
  299.       240 input "What is your telephone number";tl$
  300.       250 la=1
  301.       251 print"qq":input "Single or double labels <1 or
  302.          2>]]]1[[[";la
  303.       260 if (la<1) or (la>2) then 250
  304.       270 input "How many labels do you want to print";nu
  305.       280 print"Sqqq]]]I have the information as:qqq"
  306.       290 print "Name:     ";nm$
  307.       300 print "Address:  ";ad$
  308.       310 print "Apartment:";ap$
  309.       320 print "City:     ";ci$
  310.       330 print "State:    ";se$
  311.       340 print "ZIP:      ";zi$
  312.       350 print "Telephone:";tl$
  313.       360 print "q Your labels are "la" wide."
  314.       370 print "You want "nu" labels printed."
  315.       380 print:print:input"]]]Is this correct]]]y[[[";r$
  316.       390 ifr$="y"then420
  317.       400 ifr$="n"then 110
  318.       410 goto 380
  319.       420 :
  320.       430 ifla=2thenla=0
  321.       440 if len(ap$)>0then ad$=ad$+", Apt. "+ap$:rem concat street
  322.          and apartment so no comma
  323.       450 cz$=ci$+", "+se$+" "+zi$:rem concat city/state/zip
  324.       460 nm=40-len(nm$):ad=40-len(ad$):cz=40-len(cz$):tl=40-len(tl$)
  325.       470 :
  326.       480 rem print routine
  327.       490 open 4,4,7: rem lowercase/uppercase
  328.       500 for x = 1 to nu
  329.       510 dc=nm:dc$=nm$:print#4,nm$;:gosub700
  330.       520 dc=ad:dc$=ad$:print#4,ad$;:gosub700
  331.       530 dc=cz:dc$=cz$:print#4,cz$;:gosub700
  332.       540 print#4,cr$;
  333.       550 dc=tl:dc$=tl$:print#4,tl$;:gosub700
  334.       560 print#4,cr$;
  335.       570 next x
  336.       580 :
  337.       590 print#4:close4
  338.       600 :
  339.       610 input "Do you want more labels]]]n[[[";r$
  340.       620 if r$="y"then640
  341.       630 end:
  342.       640 printchr$(147) : rem "clear home
  343.       650 input "Do you want the same name]]]y[[[";r$
  344.       660 ifr$="y"then270
  345.       670 if r$ = "n" then 180
  346.       680 goto 610
  347.       690 rem double column routine
  348.       700 if la then print#4,cr$;:return
  349.       710 for i=0 to dc:print#4,sp$;: next i
  350.       720 print#4,dc$:return
  351.  
  352.  
  353.      The above program has almost everything needed. It is not,
  354. however, idiot proof. It does not tell the user when it is printing.
  355. And it still has a bug. So I got lazy. But it should work, without
  356. modification, on any Commodore computer from the PET 2001 to the
  357. Commodore 128 PC and on almost any printer. A user can run it without
  358. ever looking at the program itself. The program is fairly well self
  359. documenting to both the user and to the programmer, so it can be passed
  360. around on disk or on a BBS without any accompanying documentation.
  361.  
  362.      A few final notes before I give you your next buggy program to
  363. work on. First, I will not ramble on this long in the future, I
  364. promise. This one is so long so I can show you basically where we are
  365. starting and where we want to go. In the future, I will give only the
  366. original and the short revisions in the newsletter, and will put the
  367. long revision with the bells and whistles on the monthly CUCUG public
  368. domain disk. I will try to concentrate on the elementary BASIC commands
  369. for the first several months. [To keep everything together, when I pass
  370. this around, I will include the listing of the long revision in the
  371. article as well as have the long revision as a second file.]
  372.  
  373.      The buggy program for you to work on appears below. Work on it,
  374. see if you can find the bugs, and by next month I will have some
  375. comments and an example revision.
  376.  
  377.  
  378.      10 rem "Simple adding machine
  379.      20 geta$:ifa$=""then20
  380.      30 print a$;
  381.      30 if val(a$)<0 or val[a$]>then goto200
  382.      40 b$=b$+a$:goto20
  383.      200 b=val(b$)
  384.      210 if a$="+"then c=c+b
  385.      220 if a$="-"then c=c-b
  386.      230 if a$="*"then c=c*b
  387.      240 if a$="/"thten c=c/b
  388.      250 print c
  389.      260 goto 20
  390.  
  391.      This little adding machine program above does not work. It is
  392. supposed to GET a key, then IF 1) the key is a numberal key, then add
  393. the character to the string to any other numeral characters previously
  394. entered to make a multi-digit number; or 2) thte key is an operation
  395. key (+,-,*,/,), then perform the operation, print the total, and go
  396. back and get the next value.
  397.  
  398.      There are errors with the program all over the place. One of the
  399. biggest is the order in which it tries to do things. Also, look out or
  400. an insidious little error in line 30. This one will take some doing to
  401. get around, but be creative. And, good luck!
  402.      Tim Sickbert
  403.