BASIC Training

by Tom Hudson


In last issue's BASIC Training, we started examining the use of the IF/THEN statement in Atari BASIC. This issue, we continue our in-depth study with more examples and a useful PRINT USING subroutine.

IF/THEN statements without relational operators?

Usually, IF/THEN statements are used with relational operators. No, that doesn't mean they can be found working at the phone company, but that they use the symbols = (equal to,) < (less than), > (greater than), <= (less than or equal to), >= (greater than or equal to) or <> (not equal to).

In some cases, these operators are not necessary, and you will see IF/THEN statements that look like:

IF NUMBER THEN 4000
IF NOT NUMBER THEN 4000
IF NUMBER OR NUMBER2 THEN 4000
IF NUMBER AND NUMBER2 THEN 4000

These are perfectly valid comparisons. They aren't seen very often, but they are easy ways to conserve several bytes of memory as well as several keystrokes.

How does this type of comparison work? Remember that the computer deals with two conditions in comparisons: TRUE and FALSE. If there is no relational operator present, the computer will examine the expression and determine if it is zero or non-zero. If the expression is zero, the FALSE condition will be set. If the expression is not zero the TRUE condition will be set.

With this information in hand, such comparisons as:

IF X <> 0 THEN 1000

can be replaced with:

IF X THEN 1000

If the value of X is non-zero, the TRUE condition will be set and the comparison will operate the same. In addition, the new line is eight bytes shorter than the original! Eight bytes may not seem like much, but when repeated dozens of times in a program the memory savings can add up to an impressive amount.

What if we want to branch when the expression is zero? In this case we must use the NOT operator. This simply flips the result of the comparison. If the result was TRUE, the NOT operator will change it to FALSE. If the result was FALSE, the NOT operator will change it to TRUE. Using this information, it is easy to check for zero values. We simply use the same comparison as for non-zero and add the NOT operator to flip the result! A simple zero check is shown below.

IF NOT X THEN 1000

Let's assume that X has a value of 5, which is, of course, non-zero and should result in a FALSE condition when X is compared to zero. First the program will evaluate X and find that it is non-zero, resulting in a TRUE condition. Next the computer will use the NOT operator to flip the condition, changing TRUE to FALSE. Since this final condition is FALSE, the branch will not be taken. If X had a value of zero, the evaluation of X would result in a FALSE condition, the NOT operator would flip this to TRUE, and the branch to line 1000 would be taken.

What other comparisons are possible? Figure 1 shows some common comparisons and their nonrelational equivalents.

Figure 1
BEFORE:  IF X<>0 AND Y=0 THEN 1000
AFTER:   IF X AND NOT Y THEN 1000

BEFORE:  IF X<>0 OR Y<>0 THEN 1000
AFTER:   IF X OR Y THEN 1000

BEFORE:  IF X=0 OR Y=0 THEN 1000
AFTER:   IF NOT X OR NOT Y THEN 1000

These are just a few of the comparisons that are possible without using the relational operators. Try some of your own and check the memory savings by using the FRE(0) function.

What about strings?

So far we've only talked about numeric variables in comparisons. The IF/THEN statement can also compare alphanumeric information in strings. If you are not sure what strings are or how they work, you may want to read "Strings in ATARI BASIC" in ANALOG #11. This in-depth article describes how strings work and demonstrates the comparison of strings with BASIC.

String comparisons are basically the same as numeric comparisons. The only difference is the structure of the expression within the IF/THEN statement. Let's took at how string comparisons work.

In numeric comparisons, the relational operators <, >, etc. determine the relationship between the two values being compared.

In strings, the ATASCII code values of the characters in the strings are used to perform the comparison. Comparison proceeds from the leftmost character to the rightmost. As each character is encountered, it is converted into its ATASCII value and compared to the corresponding character in the other string. If the ATASCII values of the characters compared are the same, the two strings are considered equal. If the ATASCII value of one character is higher than the other, that string is considered greater. Conversely, if the character's ATASCII value is lower than the other, the string is considered less than the other.

Luckily, the ATASCII values are configured so that the closer the letter is to the beginning of the alphabet, the lower its ATASCII code number is. This makes it very easy to alphabetize lists of names. For example, the name "FRED" would come before "RALPH" because the ATASCII value for F (70) is lower than R (82).

Enter the listing from Figure 2 into your computer, type in the example strings shown below the listing and observe the results.

Figure 2
10 DIM A$(5),B$(5)
20 PRINT "ENTER STRING 1";:INPUT A$
30 PRINT "ENTER STRING 2";:INPUT B$
40 IF A$=B$ THEN PRINT A$;"=";B$
50 IF A$>B$ THEN PRINT A$;">";B$
60 IF A$<B$ THEN PRINT A$;"<";B$
70 GOTO 20
TRYSTRING 1STRING 2
1FREDRALPH
2RALPHFRED
31231234
41234512345
5HELLOhello

Comparison number 1 will result in FRED < RALPH because, as noted earlier, the letter F is lower than the letter R in the ATASCII code sequence.

Comparison number 2 will result in RALPH > FRED. This is the same result as the first comparison, but we have just switched the order of the comparison.

Comparison number 3 will result in 123 < 1234. The first three characters of the strings are equal, but when the computer tries to compare the fourth character of each, it finds that the string "123" only has three characters, while the string "1234" has four. This causes the computer to decide that "1234" is greater than "123."

Comparison number 4 will result in 12345 = 12345, a fairly obvious result.

Comparison number 5 is very interesting. It will result in HELLO < hello. The reason for this becomes clear when one studies the ATASCII code chart in the ATARI BASIC reference manual. The upper case letters' ATASCII codes range from 65 to 90, while the lower case range from 97 to 122. As a result of this structure, lower case words will always be greater than their upper case counterparts.

Try your own comparisons with the above program and observe the results. You'll soon understand the logic of string comparisons.

USING comparisons.

Now that we've covered the decision-making features of ATARI BASIC, let's look at a program that applies most of these principles.

The program listing in Figure 3 will provide ATARI BASIC users with a handy PRINT USING function. This function allows the printing of numbers in specific forms, such as dollars and cents, dates and fixed decimal places.

Type this program into your computer and check it for typing accuracy with C:CHECK or D:CHECK II. Lines 10000-10250 of this listing make up the PRINT USING subroutine, and can be added to any program. Before running the program, let's took at how the PRINT USING function works.

The PRINT USING function allows the programmer to print numbers in specific formats. Instead of numbers appearing like 7654293.5, the PRINT USING function prints the numbers in an easily-readable form, such as 7,654,293.50. Dates can be shown in the standard format 12/14/83 if desired.

In order to use the PRINT USING function, two things are needed: An EDITING PATTERN and a VALUE to be edited. The editing pattern determines the printed form of the value, and can be set up in almost any form. There are several rules that must be followed when setting up an editing pattern.

  1. The editing symbol "#" is used wherever a number is to appear. To show a five-digit number, the pattern "#####" would be used.
  2. The editing symbol "." is used to show were the decimal point is to appear. Only one decimal point should appear in the editing pattern. To show a three-digit number with two decimal positions, the pattern would be used.
  3. The editing symbol "," is used to show where commas are to be inserted into the number. Use as many commas as necessary. To show a dollar amount in the millions of dollars, the editing pattern "#,###,###.##" would be used.
  4. Other editing symbols, such as "/", can be placed in the editing pattern. They will be inserted into the edited result. An example of this is an ordinary date edit pattern, for which "##/##/##" would be used.
  5. The editing pattern should be large enough to hold any values that are edited with it. For example, if the largest number in a dollar amount edit would be $1000, the pattern is the smallest that should be used. If the number exceeds the pattern length, the subroutine will return all "*" for the edited number.
  6. The subroutine does not round when decimals are truncated. For example, if a pattern of "###.#" is used and the number is 23.0577, the edited result will be "23.0".

The BASIC program in Figure 3 will allow you to type ##,###.## and press RETURN. When asked for a value to edit, type 1895.546 and press RE- TURN. The computer should display "EDITED VALUE = 1,895.54" and ask for another pattern. Try some of your own to get acquainted with the PRINT USING function.

How it works.

The PRINT USING subroutine is easy to use. Simply set up the string variables P$, O$ and F$ as in line 80 of the demonstration program, and place lines 10000-10250 in your program. When you want to edit a number, just place an editing pattern in P$, put the number to be edited in 0$ (this is easily done with the statement "0$=STR$(NUMBER)"), and GOSUB 10000. The subroutine will edit the number and return the result to you in F$. You can then print F$ to the screen or printer as you wish.


Hopefully, this article will give some helpful insights into the decision-making power of your ATARI computer system, as well as some ideas to help you make your programs more efficient.

Figure 3

PUSING.LST is available in ATASCII format.

10 REM ******************************
20 REM *      PRINT USING DEMO      *
30 REM *                            *
40 REM *       BY TOM HUDSON        *
50 REM *                            *
60 REM * A.N.A.L.O.G. COMPUTING #16 *
70 REM ******************************
80 DIM P$(20),O$(20),F$(20)
90 ? :? "ENTER EDITING PATTERN";:INPUT
 P$
100 ? :? "ENTER VALUE TO EDIT";:INPUT 
O$
110 GOSUB 10000
120 ? :? "EDITED VALUE = ";F$
130 GOTO 90
10000 REM **************************
10010 REM * PRINT USING SUBROUTINE *
10020 REM **************************
10030 LP=LEN(P$):LO=LEN(O$):F$(1)=" ":
F$(20)=" ":F$(2)=F$:F$=""
10040 FOR X=1 TO LP:IF P$(X,X)="." THE
N PD=X:GOTO 10060
10050 NEXT X:PD=0
10060 FOR X=1 TO LO:IF O$(X,X)="." THE
N OD=X:GOTO 10080
10070 NEXT X:OD=0
10080 IF PD THEN PWX=PD-1:PDX=PD+1:GOT
O 10100
10090 PWX=LP:PDX=0
10100 IF OD THEN OWX=OD-1:ODX=OD+1:GOT
O 10120
10110 OWX=LO:ODX=0
10120 IF  NOT PD THEN 10220
10130 F$(PD,PD)="."
10140 IF  NOT OD THEN 10190:REM ***ZER
O FILL***
10150 IF ODX>LO THEN 10190
10160 IF PDX>LP THEN 10220
10170 IF P$(PDX,PDX)<>"#" THEN F$(PDX,
PDX)=P$(PDX,PDX):PDX=PDX+1:GOTO 10160
10180 F$(PDX,PDX)=O$(ODX,ODX):ODX=ODX+
1:PDX=PDX+1:GOTO 10150
10190 IF PDX>LP THEN 10220
10200 IF P$(PDX,PDX)<>"#" THEN F$(PDX,
PDX)=P$(PDX,PDX):PDX=PDX+1:GOTO 10190
10210 F$(PDX,PDX)="0":PDX=PDX+1:GOTO 1
0190
10220 IF  NOT OWX THEN RETURN 
10230 IF  NOT PWX THEN FOR X=1 TO LP:F
$(X,X)="*":NEXT X:RETURN 
10240 IF P$(PWX,PWX)<>"#" THEN F$(PWX,
PWX)=P$(PWX,PWX):PWX=PWX-1:GOTO 10230
10250 F$(PWX,PWX)=O$(OWX,OWX):OWX=OWX-
1:PWX=PWX-1:GOTO 10220
Checksum Data
10 DATA 771,338,225,293,229,755,783,19
,464,477,993,412,505,568,70,6902
10020 DATA 572,131,806,220,806,221,966
,660,949,639,288,473,620,338,330,8019
10170 DATA 575,824,336,571,332,148,399
,812,105,4102

Previous | Contents | Next

Original text copyright 1984 by ANALOG Computing. Reprinted with permission by the Digital ANALOG Archive.