--- title: "Handling Character Strings in the ZX80" type: "article" slug: "handling-character-strings-in-the-zx80" url: "http://localhost/article/handling-character-strings-in-the-zx80/" markdown_url: "http://localhost/article/handling-character-strings-in-the-zx80.md" published_at: "2020-10-27T17:18:35+00:00" modified_at: "2026-10-23T09:57:34+00:00" featured_image: url: "http://localhost/wp-content/uploads/2022/04/20230809-041332.jpg" excerpt: "Using USR(47) to find the address of a string variable and peeks/pokes to manipulate the string." post_tag: - name: "1981" slug: "year-1981" taxonomy: "post_tag" url: "http://localhost/tag/year-1981/" - name: "Tutorial" slug: "tutorial" taxonomy: "post_tag" url: "http://localhost/tag/tutorial/" - name: "ZX80" slug: "zx80" taxonomy: "post_tag" url: "http://localhost/tag/zx80/" model: - name: "Sinclair ZX80" slug: "zx80" taxonomy: "model" url: "http://localhost/model/zx80/" indiv: - name: "Hasse Taube" slug: "hasse-taube" taxonomy: "indiv" url: "http://localhost/indiv/hasse-taube/" publication: "SYNC" publication_r: id: 10243 title: "SYNC" type: "periodical" url: "http://localhost/periodical/sync-magazine/" authors: "Hasse Taube" volume: "1" issue: "3" issues_articles: - id: 26637 title: "SYNC v1 n3" type: "issue" url: "http://localhost/issue/sync-v1-n3/" pages: "6" pubdate: "May/June 1981" archive_link: false volumeissue: "v1n3" --- # Handling Character Strings in the ZX80 From the first day I tried to operate my new ZX80, I have been looking for a way to simulate some of the character-string operations possible in other programming languages, but not in the ZX80 Basic. An idea mentioned by Michael Kirkland in Personal Computer World, February, 1981, on using USR(47) to obtain the address of the end of the variables provided me with the key to start my programming tricks in the ZX80. Consider the following piece of code: ``` 100 LET A$="ABCDEFGHIJKLMNOPQ" 200 LET A=USR(47) ``` Then A is the address of the byte after the last “”. Consider also: ``` 100 LET A$="ABCDEFGHIJKLMNOPQ" 200 LET A=USR(47)-2 ``` A will contain the address of the last byte of the previous character string; in this case, A will be the address of the letter Q. In order to use this facility, you should not have any other statements between 100 and 200 in the examples mentioned above. To test this on your ZX80, enter the following short program: ``` 100 LET A$="ABCDEFG" 200 LET A=USR(47) 300 PRINT CHR$ (PEEK(A)) ``` This should give the letter G as output, i.e., the last character in a character string A$. You know, of course, that you can always get the first character in a character string by a piece of code like this: ``` 100 LET A$="ABCDEFGHIJ" 200 LET B$=CHR$(CODE(A$)) ``` Then the variable B$ will get the value A, i.e., the first character of the character string A$. It is, however, not so easy to get the last—or in fact any other than the first character. This is now possible with the use of the technique just described. Suppose you want the last character of a string variable after a value has been assigned to it by an INPUT: ``` 100 INPUT A$ 200 LET A=USR(47)-2 300 PRINT CHR$(PEEK(A)) ``` If you run this program and input, say, QWERTY, the output should be Y. In other words, if you use: ``` (line number) LET A=USR(47)-2 ``` immediately after an assignment of a string variable by a LET-statement or by an INPUT-statement, the variable A will point to the last character in the string. If you know the length of the string, it is easy to take a substring from it. Suppose you know that the length of the string is 5 as in the following example: ``` 100 LET A$="ABCDE" 200 LET A=USR(47) 300 LET B$="XX" 400 LET B=USR(47) 500 POKE B-2,PEEK(A-5) 600 POKE B-3,PEEK(A-6) 700 PRINT B$ ``` Then the output will be AB, i.e., the first two characters from the string A$. By using the example above with other values in statements 500 and 600, you could, of course, get another substring from A$. Also, if you would like to take a larger substring than just two characters as in the example, you probably would set up for a FOR…NEXT loop to do the POKE’s and PEEK’s. Suppose you do not know the length of the string variable from which you want to take, say, the second and third characters. How can you find the length of a string variable? Several methods are available. The first uses the TL$ in a loop like this: ``` 100 INPUT A$ 200 LET B$=A$ 300 FOR I = 1 TO 1000 400 LET A$ = TL$(A$) 500 IF A$ = "" THEN GO TO 1000 600 NEXT I 1000 LET A$=B$ 1100 PRINT I ``` Then the output-value will be the length of the string which you input. A much more interesting method for finding the length of a string also gives you the address of the beginning of the string. In this second method strings are internally stored in the ZX80 as follows: —One byte with a code for the name of the string; —The string itself from first character to last character; —The ending quote. The first byte contains a value which is equal to decimal 96 plus the code for a letter and which names the string. For example, a string named A$ will have 96+38=134 (decimal) in the first byte. A string named Z$ will have 96+63=159 (decimal) in the first byte. To understand these examples, you must know that the ZX80 representation for A is 38 and Z is 63. (See your instruction manual for the ZX80.) To find the address of the first byte of the string in a string variable, you must set up a loop to test for the value in the first byte, described above. Assuming you know the address of the byte after the ending quote from USR(47), this should be fairly simple: ``` 100 INPUT A$ 200 LET A=USR(47) 300 FOR I=0 TO 1000 400 LET J=A-2-I 500 IF PEEK(J)=134 THEN GO TO 1000 600 NEXT I 1000 PRINT I ``` The program above will print out the length of the string which you input, but more interestingly, after statement 1000, J will point to the first byte of A$, and J+1 will point to the first byte in the string itself.