The CBasic clinic; part 3. John A. Libertine.
The CBasic Clinic
You have probably noticed that the first two sessions in this series went along slowly and easily to get you used to the CBasic language. You should now at least be familiar with the steps involved in writing, compiling, and running your CBasic programs.
From now on, you will find that things speed up and become a little more involved. Don't let this throw you. If you can't quite get the idea the first time, don't be afraid to reread and, above all, try the program listings. You can learn quite a bit more if you see the results on your screen or printer.
Before we start this session, I want to call your attention to the error messages in CBasic. You recall there are two kinds: one shows up when you compile a program; the other when you actually run it. Your documentation lists both kinds and explains the error. A better listing appears in CBasic User Guide (Osborne/McGraw Hill), which I urge you to buy. In my opinion, the User Guide listing gives much better explanations and corrective actions to be taken.
The most common compiler error you are likely to see is ERROR SE. The error notice is printed right under the line where it occurs and reads something like: ERROR SE IN LINE 47 AT POSITION 13. SE means syntax error. You may have misspelled a key word (pritn instead of print, for example). The next most common error is US (undefined string). It means you left the quotation mark off the beginning or, more likely, the end of a string. You will, undoubtedly, make your share of errors and thus have to learn about them as you go along. Some of them can be quite tricky, so take the time to read the documentation and try to think logically and slowly.
Okay, let's try a slightly different approach this time. Take a look at Listing 1, a simple program that allows you to enter the names, addresses, and scores of a bowling team. Note that I have used special numbers (A1, A2, and so on) at the left margin. These are for ease in reference only; you do not type them in your program.
First of all, read through the entire listing. You should be able to understand most of it. Of course, there are many new statements and functions that will be unclear; we will go into these in detail, but try to get the feel and the gist of the program first. This program not only lets you enter the data but saves them in a file so you can access them anytime. We will then do another short program to print the results out on your printer.
The first new statement is the very first word: GOSUB. As in most Basics, it means go to a subroutine. The figure next to it (in this case, 10000) refers to the line number where the subroutine starts. Remember that we don't need line numbers in CBasic except when we specifically refer to one. You will find line 10000 near the end (at A68). Most programmers put subroutines at the end.
In this case, there are three of them (at lines 10000, 20000, and 30000). It is customary in CBasic to use distinctive line numbers for subroutines. In this case, I have used large even numbers starting with 10000. You could also use a decimal line system: 1000.1, 1000.2, etc. The choice is yours as long as you are comfortable with it. Incidentally, for simplicity I will refer to program lines as line 1000 or line 20. The reference numbers at the left will be called simply A1, A34, and so on.
At A1, we tell the computer: Go to a subroutine that is located at line 10000. Line 10000 (at A68) is the beginning of our old friend from Part 2, the FORNEXT loop that clears the screen. This ends at A71. Now notice that A72 has the single word RETURN. This tells your computer we have reached the end of the subroutine and the program is to return to the line following the GOSUB instruction. In this case, the program now goes back to A2. Remember, all subroutines must be followed by a RETURN.
From A2 to A7, the program displays a title screen. The multiple print statements on A5 push everything on the screen up seven lines to center the words. The colons between each PRINT are shortcuts. They mean the next instruction is to print on the following line. In this case, each instruction merely prints a blank line.
A7 illustrates two significant CBasic statements: input and line. Input stops the program and waits for you to type something. In this case, we are asking that the RETURN key be pressed. The function here is to stop the program while the operator reads the screen. At A33 and several other places, the Input requested is a name or other data. In any case, Input serves two functions: It stops the program, and it accepts your input, which is then assigned to a variable. Usually, after you input the data, you hit the RETURN key to end the input. At A7, only the RETURN key need be hit because the function here is to halt only until you are ready to proceed.
There are two basic kinds of inputs. A41 illustrates the usual one. Here you are asked to furnish a number (bowling score). The other kind is a line input. A33 is a typical example. Putting the word LINE before the variable NAME$ makes it possible to enter a line of characters and/or numbers including most punctuation marks (commas, semicolons, and so on). Ordinarily, a comma indicates the end of one item and the beginning of another. For example, if you entered:
John,Joseph,Michael each name would be considered a separate input, and you would need three variables (i.e., INPUT Name 1$, Name2$,Name3$ ). In this case, the commas are considered delimiters; they set off each item individually. If you use the line type of input, the three would be one item (assigned to one variable), and it would be stored and printed out exactly as entered.
This line input is useful in an address line, for example:
100 Main Street, Apartment 2. If you did not use the line input, the street address and apartment number would have to be two separate items assigned to two variables in the file, and the comma simply would not print out. If you try to assign such a line to a single variable, you would get an ERROR message.
One punctuation mark you cannot use in a line input is a quotation mark because quotation marks are used as the delimiters in this type of input. A simple way to visualize this is to see how CBasic stores items you input. Say you input an address:
100 Main Street, Apartment 2 If you use the regular input with two variables, here is how it looks in the file:
100 Main Street, Apartment 2 If you use the line input with one variable, it looks like this:
"100 Main Street, Apartment 2' (note the quotation marks).
In the first example, commas are the delimiters. In the second, commas are still the delimiters but not when they are within a string set off with quotation marks. You can see it better in a file that reads:
"10 Main St., Apartment 2', "Anytown, Mass.'
The commas after St. and Anytown are literals, and they print. The comma between Apartment 2 and Anytown is a delimiter and does not print. This is two separate entries, of course.
In A7, the line input serves an additional function. When you hit RETURN, you are putting a null string--a string with nothing in it into the variable Dummy$. With the regular input, hitting RETURN has no effect. The computer does nothing but wait for more input or gives you an error message. By making it a line input, hitting RETURN puts in a null string in the form of two quotation marks next to each other ("'). The computer sees this as an entry, assigns it to Dummy$, and goes to the next program line. Because we never call back Dummy$, it just serves to startup the program after a halt.
You must remember that the line type of input can be used only with string variables. CBasic does not allow this form with integer or real number variables.
In addition, compare A6 and A7 with A20. In the first case, we have a PRINT statement followed by an INPUT line. On your screen, A6 prints the line shown and, on the next line, A7 prints a question mark. At A20, the input is followed by a prompt string (a word or words) that will print on your screen. There isn't a question mark in this case, and the cursor stays on the same line. Either works. The second is usually easier and more efficient. With this background. you should now be able to understand the program completely through A21.
Now we come to one of the most powerful functions of CBasic: file handling. For some reason, this whole business of files seems to throw neophytes for a loop. Let's approach it slowly and simply keeping in mind that, for now, we will sometimes oversimplify and leave out some of the more advanced features to make things easier.
It helps to remember that a file is nothing more than data stored on your disk; thus it can be recalled anytime. You give it a name that follows the CP/M format (up to eight characters followed by an optional period and three character extension as: FILENAME.EXT). The data can be stored in two major forms: sequential and random access. The latter is more advanced and versatile, but for this program let's stick with the simpler sequential form. Sequential simply means the data are stored in a stream--one item right after the other.
The first step is to create the file. Two statements are available: create and file. The first creates a file unquestioningly. This means that if the same file name already exits, it erases it and overwrites it. The File statement creates a file only if the name does not exist on your disk. If it does exist, it opens the file (i.e., makes it available for reading or additional input). In our program, we are using this form. Once a file is created or opened, we do not refer to it again by file name. We use a number from 1 to 20 because 20 is the largest number of files we can have open at the same time. In the case of the File statement, the file number is the lowest unused number. In our programs that is number 1. The create statement requires you to give the file a number as in CREATE "FILENAME.FIL' AS 1. In either case, we refer to the file as 1 as long as it is active.
At A22, we name the file and assign it to a variable Filename$. At A24, we open the file. The first time you use this program, it creates the file. After that, the file exists and the program will open the file. This makes it possible, among other things, to add names and data to an existing file.
A25 is a key line. The IF END statement means: If in reading this file, should you come to the end of the file, then go to line 10. If we did not put this in, the program would read to the end of the file and, finding no further data, would cause a runtime error that would crash the program. A27 (line 20) illustrates the READ format. As I noted, the file is referred to as 1. The format for a read is:
READ #X semicolon variable comma variable comma and so on (where X is a file number from 1 to 20). Note that an IF END is not executed immediately. It only executes when and if you have read all the way through a file.
If you are running this program for the first time, the IF END executes at line 20 (A27) because it tries to read a file with no data in it. The program goes to line 10. If the file already exists, the read executes and reads the first series of the data (Name$ through String3). As you can see at A29, the program then returns to line 20 and reads the next series and so forth until the end of the file is reached. What is happening here is that the data are taken out of the disk file and placed into memory. When the end of the file is reached, the IF END executes and the program goes to line 10 (at A31). Just to illustrate that line numbers in CBasic do not have to follow any order, note that line 10 comes after line 20 in this program.
You should be able to figure out A26 and A28 (along with similar lines later in the program). This is a simple way to count the number of entries you make. At the end, we can print out the number of names in the file.
When the program gets to line 10, the GOSUB 10000 repeats the clear screen routine and the program begins to ask for inputs at A33 through A47. Note that after the three numeric inputs (for scores) there is an error trap line, which simply catches an input that is less than 1 or more than 300 (the range for bowling scores). You should be able to trace this for yourself now.
This is not a very sophisticated error trap, but it does not have to be because the operator has a chance to proofread his entries later. This error trap simply generates the warning message. This happens after the inputs at A50 through A57. I think you should be able to follow the logic without my going over each line.
At A58 (or A62 depending on responses just preceding) the program has a GOSUB to A73. This is where the data are written onto the disk. The format is virtually identical to the READ statement except the command is PRINT # X instead of READ #X (where X is the file number).
Closing The File
At some point, the program must come to A63. To ensure that the data are safely transferred to disk, we must close the file. The command is simple: CLOSE X (X = file number). We are now at the end of the program. From A64 to A67, the final count is taken and printed on your screen.
The STOP statement at A67 is important. It prevents the program from continuing along and executing all the subroutines that follow. Unlike some Basics, we cannot use END here. An END in CBasic stops the compiler (which we don't want, of course), so the STOP is used instead. The difference is simple: END stops the program cold at any stage of compilation. STOP stops the program only in the runtime mode.
When you have written the program, store it, compile it (CBAS2 BOWL), and then run it (CRUN2 BOWL). Put in four or five names and scores. Note that you have three lines for addresses. If you do not need all of them, you merely enter RETURN (a null string, remember?). After you do this, you can read the file. Go to the A > prompt in CP/M and enter: TYPE BOWLING.FIL. The file will show up on your screen. Note the way the data are stored. The first few items (the ones entered with Line Input) are set off in quotes. The last three (entered with plain Input) are not. A typical line in your file should look like this:
"J. Jones', "10 Main St.', "Anytown, CA 90000',"',195,183,179 Notice the null string between 90000 and 195.
Now you should run the program a second time and add a few more names and scores to illustrate how to add to an existing file. Type it out on your screen again to see the additions.
Now would you like to see a formatted print out on your printer? Just enter the program in Listing 2. We will go into the whys and wherefores next session, but for now you must try it as a solo flight. Type, store, compile (CBAS2 PRINTER), and run it (CRUN2 PRINTER).
Your assignment before the next session is to try to figure out the logic of the PRINTER.BAS program from your documentation or the CBasic User Guide. Especially look up two new statements: the LPRINTER and CONSOLE commands. Good luck.
Table: Listing 1.
Table: Listing 2.