String Arrays in Atari BASIC
Charles Brannon
This article describes a method to simulate string array handling in Atari BASIC. If you already know what a string array is, skip ahead a bit. Otherwise, read on...
An array is essentially a list. For example, the numeric array A could hold a list of monthly amounts. A(l) would hold January, A(2) would contain February's monthly total, and so on, A(12) containing December's amount. To print the amounts from month one to month twelve, the BASIC statement:
FOR I = 1 TO 12 : PRINT A(I) : NEXT I
could be used. As the amounts were printed, the computer would optionally add the amounts up and print a yearly total. Numerical arrays also have many uses in mathematics.
If we wanted to print the name of each month along with the amount for that month, string arrays would come in handy. For January, the string array M$ might hold "Jan" (i.e. M$(1) = "JAN"). Once all the strings were defined, we could print the months along with the amounts:
FOR I = 1 TO 12 : PRINT M$(I), A(I):NEXT I
Alternately, a string array could contain a list of player's names in a game. PRINT P$(PLR) could give the name of player number PLR.
It is a fairly well-known fact that Atari BASIC is not Microsoft BASIC (although a Microsoft BASIC for Atari should be released soon). The designers of the BASIC decided to use a different way of manipulating strings than Microsoft did. The statement PRINT LEFT$(A$,4) in Microsoft BASIC would produce the same effect as PRINT A$(l,4) would in Atari BASIC. Unfortunately, this notation precludes the use of string array notation.
Nevertheless, it is possible to produce the same effect as string arrays under Atari BASIC. The technique used here is similar to the one used in the string sort program in the back of the Atari Basic Reference Manual.
Essentially, the solution is to partition one very large string into several substrings. Each substring will be an element of the larger array. First, let us review the format that Atari BASIC uses to handle substrings. Say that A$ contains "Hello, how are you?". To print the word "how" we would specify A$(8, 10), the first argument, eight, being the starting position within the string and the second being the ending position of the substring, in this case, 11. We use this notation to recall or store any element from the main string. There are some non-Microsoft notations to specify an element in a string array. PRINT A$(2,3,6) would print the characters from three to six in the second element of A$. We will use an "unraveled" string to simulate this.
Say we want to set aside an area of memory for 10 strings, each string having a maximum length of 20 characters. Actually, this is required in Atari BASIC anyway. Since the DIM statement only takes one argument, the total number of characters in the string, we would enter in the program the statement: DIM A$(200), as 10 strings of 20 characters each would be 200 characters in total length. Now, to define each string, we must specify the starting location within the main string and how many characters to store at that location. If the string to be stored was T$, and E is the element that T$ is, then the statement to store T$ in A$ would be:
A$( (E-1) * 20 + 1, E * 20) = T$
If T = 2 (i.e. T$ would be the second string in A$), then the statement would reduce to: A$(21,40) = T$, and indeed, the area of A$ reserved for element 2 would be characters twenty-one to forty.
To recall an element from the string array, the statement need only be reversed. The element position of T$ still needs to be specified.
T$ = A$(E - 1) * 20, E * 20)
The "20" in the statements is of course the maximum number of characters in any element in the array. It could be specified a a variable at the start of your program.
There are still a few problems with this scheme. Although both CLR and RUN clear out the simple variables, the arrays and strings are left untouched. Therefore, before one can store a new element in the main string, a possible previous one must be cleared out. If the two previous statements were renumbered so as to be subroutines, then T$ could be set equal to twenty spaces first, GOSUB the storage routine, then store the actual value of the element. The example program should demonstrate this.
When printing the string, any character less than twenty characters will have trailing spaces. This could be corrected by a routine that strips off these spaces, but it might have a hard time if multiple spaces could be present in an actual element. Therefore, it might be advantageous to keep track of the length of each element so that only the proper number of characters would be printed. The length of each element in the array could be stored in a numeric array, say L. Therefore, the mini-subroutine to store a string element would be:
20000 L = LEN(TJ) : IF L > MAXLEN THEN L = MAXLEN 20010 L(E) = L : START = (E - 1) * MAXLEN 20020 A$(START, START + L - 1) = T$ : RETURN
This subroutine requires that A$ and L be properly DIMensioned at the start of the program, MAXLEN equals the maximum length of each element, T$ contains the string to be stored, and E contains the number of which element T$ will become.
To recall an element, set E equal to the element number, and call the following routine. MAXLEN must be predefined (see above) and the strings and array L DIMensioned.
3000 START = (E - 1) * MAXLEN : T$ = A$(START, START + L(E) - 1) : RETURN
To sum up, I have presented here a technique to simulate the use of string arrays. Undoubtedly it is not the only way, so be creative! Nevertheless, the two subroutines can be the foundation for programs of increased sophistication, as string arrays add a new dimension to programming efforts!