In the last chapter we found that the program we wanted was too big for the memory you are starting with. Alas! This problem does not go away. But all is not lost. In this chapter we will tackle the worst memory gobbler of all: financial programs. No, not a General Ledger program in your computer (you do not have enough memory), but a checkbook balancing program. To make this fit, you will learn two different ways to save program space.
The first way to save space is a feature which came in with some of the earliest computers (30 years ago). It is similar in concept to the programming trick I showed you in the Roman Numeral program in Chapter 4. But it is a well accepted concept that even your computer scientist friend will approve of. The concept is this: Whenever possible, we use the same routines and lines of program over and over.
One way to do this is to use a variable to count the number of times you have been through the routine, and when you reach some preset count, you quit. This is called a loop. We used this technique to count the "X"s and "I"s in the Roman Numeral program. Some computer languages have special ways to set up loops in the program; TINY BASIC does not because you can do the same things with a LET and an IF.
Another way to use the same routine over and over is to put it in what we call a subroutine. A subroutine is simply a routine which is set apart like a doctor's office or a shoe store, so that any time the program needs to have done what that subroutine is good at, the program calls the subroutine to do it. For example, if you need a pair of shoes, you go to the shoe store; if someone else in your family needs shoes, again, another trip to the shoe store. If someone gets sick, or needs a shot, you go to the doctor's office. You do not go to the doctor's office to buy work boots, and the shoe clerk is not allowed to administer vaccinations. When you finish at the shoe store or the doctor's office or the library, or wherever you went, you return home, or maybe you go run some more errands. Now you could have sat at home the whole time, and had your own private shoe clerk bring you shoes, and your own private nurse give you shots, and so on, but that is quite expensive.
Now if you have the general idea, let's see what that means in programming a computer. Each subroutine is made up of lines of program, just as you are already familiar with. Perhaps we might use line numbers in the thousands to keep them out of the way, but that is not necessary. Each place in the program where we need that particular function done, we insert a line with the command GOSUB (for GO to SUBroutine) and the line number of the first line of the subroutine, like a GO TO command. When TINY BASIC sees the GOSUB command, it makes a mental note of which line the command is on, then does a GO TO to the subroutine. When the subroutine is finished doing its thing, it ends with a RETURN command, which tells TINY, "find the line that last GOSUB was on, and continue after that."
Perhaps a practical example will help. We are going to do a checkbook balancing program, and we need to print out dollars and cents. You already know how to do this, so I need not get into great detail. But my point is that we want to print out starting balance, the check amount, and the ending balance, each with a dollar sign, decimal point, and so on. But neither you nor I want to write that dollars-and-cents routine three times. So we will make a subroutine out of it.
We will assume that the dollar amount is in variable D. and the cents amount is in variable C. Thus we can handle balances up to $32767.99 (you are obviously not that rich, and if you were, you would know better than to keep that much money in your checking account). The subroutine starts on line 1010:
1010 PRINT "$";D;".";Notice that in line 1040, you type the word, "R","E","T","U","R","N", then hit the RETURN key. We will put the running balance in variable M (for "money") and the cents of that balance in P (for "pennies"). The first thing to do is print out the balance:
1020 IF C<10 THEN PRINT 0;
1030 PRINT C
110 PRINT "BALANCE IS"Now we want to accept the check amount in dollars and cents. As you know, TINY cannot handle a decimal point, so me will pretend that we took our schooling in Europe and use a comma instead of a period for the decimal point. It turns out that TINY is able to accept several variables of input on a single line if the variables are separated by commas. But this only works inside a program. The INPUT statement must have a line number for it to work:
120 LET D=M
130 LET C=P
140 GOSUB 1010
160 PRINT "CHECK OR DEPOSIT"When you use this program, you will type a minus sign in front of the check amounts, a plus in front of the deposits. The minus will come through as a negative amount in D. I suppose you are more likely to write a check for less than $1 than you are to make such a small deposit, so we further assume that if the dollar part of an entry is zero. you probably intended it to be -0 (with non-zero cents). If both dollars and cents are zero, the program quits:
170 PRINT "DOLS,CTS";
180 INPUT D,C
190 IF D=0 THEN IF C=0 THEN ENDNotice also that if the balance tries to go negative, we will reject the check and put the money back into the account. I know, most banks have a policy of accepting a certain amount of over drawn checks and charging you for them. You can fix the program to do that later. Oh, we still need to do the actual adding and subtracting. We define another subroutine which notices when the cents in P have gone over 100, then bumps them back down and adds $1 to M.
200 IF D<=O THEN GO TO 310
210 PRINT "DEPOSITING"
220 GOSUB 1010
280 GO TO 110
310 PRINT "WITHDRAWING"
320 LET D=-D
330 GOSUB 1010
370 IF M>=0 THEN GO TO 110
380 PRINT "OVERDRAFT"
390 GO TO 230
1110 LET M=M+P/100Depositing is easy. Add the dollars; add the cents; then call the subroutine to check. Withdrawing might go negative in the cents, so we borrow a dollar from M, do the subtraction, then call the subroutine to put the dollar back if it was not used:
1120 LET P=P-P/100*100
230 LET P=P+CNow if you got all that program into your computer without a memory overflow (message number 8) you have more memory than I give you credit for. If not, don't worry about it; I overflowed too. Let's see what can be done about it.
240 LET M=M+D
250 GOSUB 1110
340 LET P=P+100-C
350 LET M=M-D-1
360 GOSUB 1110
First I should mention that all the tricks which I will tell you about in the next page or so will not make your program run any better or worse; but they will make it harder for you to read the program and figure out what it is doing. This is not a minor point, because most of your time on the computer, as I said, will be spent in trying to find program bugs. If you can write a program and fit it into memory without doing any of these space-saving tricks, do so. It will save you time and aspirin. But if it just will not fit, then go ahead and squeeze out the space.
I never mentioned it to you, but TINY ignores all spaces in program lines, except inside quoted text for printing. The spaces are there to make it easier to read. The following two lines mean exactly the same thing:
200 IF D <= 0 THEN GO TO 310But notice how much easier it is to read the first line. In a PRINT command, however, everything enclosed by quotes is printed, including the spaces. If you take spaces out there, the printed message will not look the same. Do not sacrifice pretty print messages for space. This makes the difference between a "hack" and an elegant piece of software. You might notice In this regard, that TINY BASIC itself is somewhat of a hack: All those error messages are compressed into numbers, which are not pretty at all.
Already you notice that we could save a couple dozen bytes by leaving spaces out. But that is not all. TINY BASIC knows that LET and IF are the only commands with the "=" character. Well, not all IFs. But every LET command has one letter (the variable name) followed by the "=" followed by some computation. So, if there is no "LET" it is still possible for TINY to figure out that this was meant to be a LET command. Since this is one of the more common commands in a typical program, saving three bytes this way is a great help. The following two lines mean the same thing in TINY BASIC:
120 LET D=MSimilarly, If a line starts with the letters "PR" it is pretty certain that the next three leturs will be "INT". You know that, and TINY knows that, so if those three letters are missing, TINY just pretends that they are there. See how much that saves:
1030 PRINT CBe careful! The command "PRI" prints the number in variable "I", so if you misspell the word "PRINT" TINY may print out the value in variable "I" then stop with error message number 73.
What about IF commands? These are also quite common. Do you have any difficulty understanding that these two lines are saying the same thing?
200 IF D<=0 THEN GOTO 310Well, TINY has no problem either. The word "THEN" may be omitted. In some other computer languages the word "THEN" is necessary to tell where the end of the comparison is. This is not true in TINY BASIC since the rest of the line always begins with a command name (or maybe a LET command, but there is still no confusion).
200 IF D<=0 GOTO 310
With them compactions in mind, let's look at the check balancing program again:
110 PR"BALANCE IS"I will let you think up your own sample data for this one.
160 PR"CHECK OR DEPOSIT"
Two things you might notice in this program. First. I did not bother to remove the spaces after the line numbers. This is because TINY takes those spaces out anyway. You can see this if you type these two lines:
1 2 3 4 5 E N DAfter the first letter in line 12345 all the extra spaces go into memory. The other spaces are removed when TINY discovers that the line begins with a number, so the line number is saved with no spaces in it or after it. The LIST command automatically puts one space back in between the line number and the rest of the line.
L I S T 1 2 3 4 5
The other thing you might have noticed, is that there is no END command at the end of the program. Since the last command in the program atways goes back to the line after the GOSUB, TINY never gets a chance to see whether there is an END there or not, and you might as wtll leave it out if you are pressed for memory space. It is usually a good idea to put it in otherwise, so that when you look at the program next week you know that it is all there.
Now, if you have a single 4K memory board and the 256 bytes that came with your basic ELF II, you should have about 20 bytes of memory left unfilled. How do I know? I have a little program I use to measure the amount of available memory:
1 B=B+2After you type RUN, the two-line program will start eating up memory at the rate of two bytes per GOSUB. None of these GOSUBs ever RETURN, so the saved line number just sits there using its two bytes of memory. Pretty soon (or after a long time, if you have a lot of memory), all the memory space is used up, and the program will error off with some message like "!424 AT #1 ". Since there was no END in the program, you have to type the "END" in by hand (to clear out all those saved GOSUBs), but then you can ask how many there were. The program carefully kept count in variable B, so that represents the number of remaining bytes in memory. How many of these are actually available depends on what your program does (i.e. if it uses a lot of GOSUBs or has very complicated computations, more memory is needed for that, leaving less available). With a single 4K board, you normally have about 400 bytes of program space. Oh, be sure to remove lines 1 and 2 before you try to run the real program.
PR B;" BYTES LEFT"
There is a way to save memory in a different sense which I think you will find useful. That is, it saves the program in memory, so that you can load it back in next week without retyping the whole thing. It is easy to use; just type:
SAVETINY will tell you to "TURN ON RECORD" and "HIT KEY". You must be sure the Cassette Out terminal from your ELF II is plugged into the microphone jack of your cassette recorder, and that it is in the Record mode. Oh, also put a binak tape in. If you record onto your TINY BASIC tape, you may have to buy a new one. After starting the tape, press the space bar or some other key on the keyboard, and the program will be saved. When it is finished TINY will come back with a colon prompt and you can turn off the recorder.
To load the program back in, just type LOAD and turn on the cassette recorder in the Playback mode, with the earplug jack connected to the Cassette Input terminal of your ELF. If it reads in ok, you will get a colon prompt. If not, it will tell you "TAPE ERROR" and you must try again.
One more thing I should mention, before you write too many unreadable programs. You may have noticed that I did not use line numbers 100, 1000, or 1100 in the check balancing program. These were being saved for comments to remind us of what their respective parts of the program were supposed to do:
100 REMARK: PRINT BALANCE & READ INPUTTINY BASIC knows that you ought to put notes to yourself in your program, so if the command begins with "REM" the rest of the line Is Ignored by TINY, but left In the program for you to read. Obviously I did not put these in because they did not fit. That is just about the flimsiest of excuses for not putting remarks in your programs.
205 REMARK: MAKE DEPOSIT
300 REMARK: WITHDRAW CHECK AMOUNT
373 REMARK: NOTICE OVERDRAFT
1000 REM SUBROUTINE TO PRINT MONEY IN D&C
1100 REM SUBROUTINE TO VERIFY CENTS<100
You now know almost all there is to know about TINY BASIC
and how to write programs. In the next chapter we will look as some of
the special ways your TINY BASIC can work with numbers
(besides computing and printing).
Back to Top
Continue with: 6 -- The Plot Thickens