The CBasic clinic; part five. John A. Libertine.
The CBasic Clinic
Those of you who have been looking for a "practical' program of a more elaborate one should be pleased with this month's tutorial. It will not only be little more of a challenge, but it can be adapted to use in the real world.
The program is adapted from one I use every month to print out a profit and loss statement for my own business. I have simplified it a bit to keep the listing somewhere within the bounds of reason. However, you can expand and modify it to suit your requirements. This program assumes you are on a "cash basis' accounting system and use a "one writ' checkbook system of some kind (such as sold by NEBS) or a bookkeeping system like The Dome Book.
Don't confuse this with a computerized checkbook. You do not enter each individual check. You enter categories (examples: Gross Sales this Month or Automobile Expenses). Either of the above types of systems will give you the total for each category which is what you enter. You can also enter the Beginning Balance as it appears in your checkbook each month. Doing this automatically provides a proof that the figures are entered correctly since the beginning balance minus outgo plus income will equal the ending balance (new balance).
Now that you have been tempted, let's digress a bit. The program contains a good deal of what has been discussed in our previous sessions. There are a few minor new functions and one very major one. This latter one requires a bit of explanation. We are about to explore arrays or subscripted variables. (For all practical purposes, the two terms can be used interchangably.)
Let's start by looking at a couple of simple variables:
Now, let's convert them to subscripted variables:
Variable.name$ (1) Number.variable(1)
The 1 in parentheses indicates that there are several other variables with the same base name. The (1) is a subscript. That subscript can be any number from zero (although most programmers use 1 as the lowest number) to a number limited only by the memory in your computer. From a practical stand-point, the larger number is usually smaller than 100 and rarely larger than a few hundred.
With this in maind, let's look at two ways of assigning variables to three name strings:
Name2$ = "Joe'
Name3$ = "Harry'
If you think about it, the two different ways of assigning variables have a great deal in common. You could actually print out the variables in the same way as, for example:
PRINT NAME 1$, NAME2$, NAME3$ or
PRINT NAME$ (1), NAME$ (2), NAME$ (3)
Assuming you have assigned the same names to each, the printout would be indtical in both instances. So why bother with the subscripted variables at all? Let me give you just one example. Let's assume you have a list of 50 names. You want to print them out one mane to line. With the regular variable format, the output portion of the program would look something like this:
PRINT NAME3$ etc. for 50 lines.
Now look how it can be done using subscripted variables:
FOR 1% = 1 TO 50
PRINT NAME$ (1%)
You have just reduced 50 program lines to three. And that is just the beginning. The significant value of subscripted variables is the the subscript itself (that portion in parentheses) can be made into a variable as above. All kinds of shortcuts and sophisticated handling techniquest are made possible. This can be especially useful for writing to and reading from files, in inputs and, a we have just see, in printouts. our program this session takes advantage of this ability in several ways. If it were not for this, the program could easily run three to five times as long as it is.
You should also know that subscripts come in various degrees. So far, the one you have seen above are one-dimensional arrays or one-dimensional subscripts. You can have two-dimensional arrays like String$ (1,1) or three-damensional arrays like String$ (1,1,1). We will barely scratch the surface of multidimensional arrays, but bear in mind that they are available and useful in some circumstances.
In some Basics, you can use arrays up to a given number without having to pre-declare them (dimensioning is the courect terminology for this). This is not true of CBasic. There is no default setting. You must dimension all arrays in advance, and the DIM statement must be only one in the program line.
For example, if you were going to use the 50-name listing above, you would need the following line in your program before using the array:
DIM NAME$ (50)
You are telling CBasic to dimension a string called NAME$ to accept up to 50 subscripts (actually 51 if you count the zero). Naturally, you are not restricted to string variables. You can use integer and real number variables in arrays (NUMBER%(1) or REAL.NUMBER(1) for example).
Some instruction books make a big deal out of arrays. One even spends the better part of an entire chapter pointing out the difference between an array and a matrix. Don't get upset by all this. If you simply remember that VARIABLE1 and VARIABLE(1) are exactly the same in every way except that the latter gives you more flexibility, you will be able to use the technique without getting involved in the technicalities.
You do have to remember to dimension an array before using it. Otherwise, they should present no real difficulty. The best way to learn about arrays is to use them. The program this month should give you enough practice and insight in the use of one-dimensional arrays to make them fairly clear.
Although the program this month does not use multi-dimensional arrays, let's take a quick look at how a two-dimensional array works so you can compare. Look at this printout:
Simply think of these as nine names arranged in three equal lines. You could, of course, assign them as individual variables (A$, B$, etc.). Or you could use a two-dimensional array. You could call the three horizontal lines 1 to 3 and the three vertical columns also 1 through 3. That means the word fox would be iline 2 of column 3. In an array, the would be shown as WORD$ (2,3). That is purely arbitrary, of course, because you case, for would be in column so the colunm comes First. In the case, for would be in column 3 of line 2 and the variable would be: WORD$ (3,2).
Can you now imagine a three-dimensional array? Try to visualize nine more names arranged behind or under the first ones above. Think of a three-dimensional array as a layered cube. Each serise of columns and lines are arranged in levels or tiers. In our example, the second tier might look like this:
If this were placed behind or under the first nine words, the word opal would be behind or under fox. We could then say: opal is in the second tier of the third column in the Second line. If you set up your array in that order, you can reach Opal with WORD$ (2,3,2). Or you could set it up so: Opal is in the the third column of the second line in the second tier. Then you would have to make your variable read: WORD$ (3,2,2). We now have two "levels,' but there is no reason you have to stop at two.
Don't be confused, however. if you add a hundred tiers or levels, you are still in a three-dimensional array. You have three dimensions: horizontal, vertical, and depth. Can you
begin to visualize this? If so fine. If not, don't let it bother you. It will come with
practice when the need arises.
Now, can you visualize a four- or five-dimensional array? If you can, please write and explain it to me because my mind just can't think that way. A math whiz might find use for htem, but it is doubtful that you or would. From a practical standpoint, one-dimensional arrays will frequently be used, two-dimensional will sometime be helpful, but you will rerely use three-dimensional arrays and orobably never have to concern yourself with four or more.
With this introduction, let's go into this month's program.
You can name it anything you want. I have used PROFLOSS.BAS (for profit and loss). As you will recall from last session, long programs do take up disk space, so plan in advance. The base program (PROFLOSS.BAS) will occupy between 10 and 14K of memory. The intermediate (PROFLOSS.INT) program will need about 5 to 8K.
Each month, you will be writing two files that use up about 2K each. Simple arithmetic tells us you will be needing close to 50K by the end of the year. I have my program (which actually is somewhat larger) on a disk with CBasic and WordStar plus a few utilities like STAT. Since my system is a double density 8 disk, that presents no problem.
If you have small disk capacity, you might consider putting all the programs and files on a separate disk. This means you must change all the program and file names to include a prefix (B: most likely). As just one example, the first file to be named is done in the line:
LET FIL MONTH+'.FIL'
If you want it on disk B, change the line to read:
LET FIL "B:'+MONTH+'.FIL'
If you do this, be sure you do it with all file names.
Okay, let's start reading through the program listing. The long REM statements at the beginning and throughout the program need not be typed in since you already have aprintout of the entire program. If you did not have the printout, however, they could be vital weeks or months later when you wanted to make a change or correction.
Note that there are six major variables, all of them subscripted. S$ is for the string descriptions (Gross income, Sales Expenses, etc.). The other five are all numeric variables associated with each of the strings. A is the figures you enter for the current month; B reads out the previous month's figures for year to date; C computes the new year-to-date figures by adding A and B (current month plus previous year-to-date); P computes the percentages for each A figure based on the number divided by the gross sales times 100; P2 does the same for the C figures to give the percentages on the new year-to-date basis.
You might notice that the above are all short, one-letter variables. This may seem strange when I have pointed out that a feature of CBasic is to allow long variable names. In this case, I am using short variables for two reasons: 1) to keep the listing reasonably short for Creative Computing; 2) to make it easier to type out the long output lines at the end of the program. In general, it will pay to use longer variable names.
Immediately under the descriptions of these variables is the all-important DIM statment that dimensions each of the variables to accept up to 22 different inputs.
If you change the program to you own bookkeeping system, you will probably have to change the number 22 to whatever is needed in your case. My own program, for example, is dimensioned to 47 subscripts.
The next section simply assigns the string varibles from 1 through 22. Note that you will enter only 14 numeric imputs for these strings. The other eight numeric variables are computed by the program. I have typed those strings which will have computed numeric figures in all caps to help you visualize this.
The next section of the program clears the screen and presents a title screen. By now, this hould be "old hat' to you. Next, the program asks that you type in the month for which you are going to enter the figures. You will also see a rather simple correction routine here. This will be used frequently throughout the program. It allows the operator to proofread the entries on the secreen and re-enter if a mistake has been made. The same type of thing immediately follows as you are asked to type in the company name.
Now comes an important section that will convert the month you entered into a filename. The first step is to be sure all the letters are in uppercase. The UCASE[X] function does this. It says to convert all letters in the string X$ to uppercase. If you already typed it in uppercase, that is fine, but it will convert January, or january to JANUARY.
Next we will take the first three letters of each month as part of the filename. We use the LEFT$ (X$, N) function to do this. This simply takes the first N letters of X$ (three in this case) starting at the left. In other words, JANUARY becomes JAN. This will be used shortly in the filename.
Now notice the line that reads IF MONTH "JAN' THEN GOSUB 2000. This is necessary to make a special previous month file for the first month of the year. That file will have all zeros for numerics. Thus the first time the program is run, the year-to-date will be the same as the first month (a first month figure plus zero will equal the first month figure). Take a look at the subroutine at line 200 near the end of the listing. You can see how using subscripted variables simplifies this task. You must remember that the program is now set up with January as the first month. If any other month is your first month, you must make changes as indicated in the REM statements throughout the program.
The next 12 lines assign a previous month for each month. This will be needed for the previous month filename.
The actual filename for the current month is figured next, and the file itself is created. Now inputs are called for and assigned to A(N) viariables (N being a number from 1 to 22). You should be able to figure out this part of the program from past experience. The only real difference is the use of subscripted variables, which by now you should understand. Notice that some variables are computed as you go along. The Total Direct Expenses for example is computed by LET A(5)@(2)+A(3)+A(4). In this case, you are not asked to enter an input for A(5). It is a computed variable.
At the end of the input module, the inputs are read into the file on disk using only three lines thanks to the use of the array. The file is then closed, and the output module begins. Three files are named next. The first two exist on disk, and they are read into memory. The third is created after adding A variables to B variables (add the current month figures to the year-to-date figures). These are the C figures. This last file is written to the disk; the file is closed to assure the numbers are in the file; and then the file is immediately re-opened. We now have three files both on disk and in computer memory. It is then a simple matter of computing the percentages for both the A and C figures, and we are ready to printout.
Simple PRINT USING statements are used for the Gross and year-to-date gross figures. After this, the rest of the printout uses a long format string to set up a column format which will be printed with the PRINT USING statement. You saw how most of this was done last session, but note a new type of format which looks like this:
This format is used for strings not numbers. Basically, it takes a string variable and prints out the number of characters between the first and last slash mark. The numbers in between are not necessary. You can use blanks or any characters. In our case here, there are 20 spaces between the slashes. Add two spaces for the slash marks themselves, and you have a total of 22. This means a string longer than 22 characters will truncate at 22 spaces. It also means a string shorter than 22 characters will print the characters and then print spaces up to a total of 22. For example, the string Cash Flow would printout as follows (if you consider the lowercase s to be a space):
Cash Flows s s s s s s s s s s s s s
The rest of the long format string then uses numeric formats as we discussed last session. Just remember that in a long, single line format such as we are using here, the spaces between the format strings are counted as part of the string. Thus if you put four spaces between two numeric formats, those four spaces will always print out. This helps to space for column formats and assures that all the figures will line up with a decimal point or with the last digit.
The printout itself should be simple to understand if you go over it carefully. However, an even better way to visualize this is to enter the program and print it out. Nothing can take the place of actually seeing the results on your screen or printer. Look at Figure 1. This is how your printout should look if everything goes well.
At the end of the printout, the three files are closed, and the program ends. Again, note the STOP between the program end and the start of the subroutines. Remember you cannot use an END here. If you do, the compiler cannot go on to compile the subroutines, and your program will not work.
You have your work cut out for you. Try revising this program to fit your needs (either for business or for a home budget). It is not as difficult as it appears at first. Give it a good try. The results are worth the effort. More important, if you really understand what you are doing, you are close to the point at which you can start to write some programs on your own. To help you do that, our next session will go into the planning and thinking which you must do before sitting down at your computer.
Table: Listing 1.
Table: Figure 1.