This program implements a telephone directory application that stores up to 200 name-and-number entries in a two-dimensional string array dimensioned at 200 rows of 32 characters each. Entries are input interactively with a confirmation step, then concatenated with a space separator into the DIM D$ array. After data entry, a bubble sort routine (lines 220–350) arranges records alphabetically using string comparison, printing each sorted entry as it is placed. A substring search (lines 500–560) uses BASIC’s slice notation — D$(A)(TO F) — to match the user’s query against the leading characters of each stored record, then prints the remainder of the record (the phone number portion) upon a match. An LPRINT loop at line 465 provides hardcopy output of the directory in reverse order.
Program Analysis
Program Structure
The program opens with a GO TO 360 at line 15, jumping immediately to the main menu, bypassing the data-entry and sort routines. The logical flow divides into five distinct functional blocks:
- Lines 20–210: Array initialization and interactive data entry loop
- Lines 220–350: Bubble sort routine, triggered when the user exits the entry loop
- Lines 360–480: Main menu dispatcher
- Lines 500–570: Name search routine
- Line 9998:
SAVEwith auto-run
Data Storage
DIM D$(200,32) at line 20 allocates a fixed 6,400-byte block for up to 200 records, each padded to exactly 32 characters. Name and telephone number are concatenated with a single space separator via LET D$(D)=B$+" "+C$ at line 170. Because the array is fixed-width, all rows are space-padded to 32 characters automatically, which is important for the sort comparisons. The variable D doubles as both the FOR loop counter and the record count, so after the entry loop exits (via GO TO 210 rather than running off the end of NEXT D), D holds the index of the last entry added.
Sorting Algorithm
The sort (lines 220–350) is a selection sort, not a bubble sort despite the structure superficially resembling one. Variable G starts at D (the last filled index) and decrements each pass. Z walks from 1 upward; when D$(B) > D$(Z), the two entries are swapped using Q$ as a temporary. After each swap the inner walk continues from the same Z. The result of each pass places the lexicographically largest remaining record at position G, which is then printed (line 330) and the window shrinks. This means sorted entries are printed to screen as they are finalized, giving the user visual feedback during sorting.
POKE 23692,0 at line 216 resets the scroll counter so the screen does not pause with “scroll?” during the sort output — a standard Spectrum/2068 idiom.
Search Routine
The search at lines 500–570 uses BASIC string slicing: D$(A)(TO F) extracts the first F characters of each record (where F=LEN A$), performing a prefix match against the user’s input. On a match, D$(A)(F+1 TO ) prints the remainder of the record — ideally the space-separated phone number — and returns to the menu. Only the first match is reported; the loop does not continue after a hit.
Menu and Navigation
The menu at lines 360–480 uses a numeric INPUT B and a chain of IF statements rather than ON ... GO TO. Option 2 (“add new names”) executes NEXT D directly, resuming the FOR D=1 TO 200 loop that was left suspended — a clever reuse of BASIC’s loop state. Option 4 saves the array with SAVE "DIRECTORY" but does not reload it on startup, so there is no LOAD option in the menu. Option 5 prints the directory via LPRINT iterating from D down to 1, producing reverse-entry order on the printer rather than sorted order.
Notable Techniques
- Reuse of the suspended
FORloop variableDas both counter and record-count sentinel. - Prefix-match search using open-ended slice notation
D$(A)(TO F)andD$(A)(F+1 TO ). POKE 23692,0to suppress scroll prompts during bulk screen output.INVERSE 1andFLASH 1used inline withinPRINTstatements for user-interface emphasis without custom UDGs.- Confirmation loop at lines 150–160: if
E$is non-empty (user typed something before ENTER), entry restarts; an empty ENTER accepts the record.
Bugs and Anomalies
- The
LPRINTloop at line 465 iterates fromD TO 1 STEP -1, printing in reverse entry order rather than the sorted order the sort routine produces. If sorting has been run, the sorted data is inD$()but the printout walks it backwards. - There is no
LOADoption in the menu, so a previously saved “DIRECTORY” file cannot be retrieved within the running program. - The entry loop uses
FOR D=1 TO 200but the array is dimensioned to 200; if all 200 slots are filled and the user presses ENTER to continue,NEXT Dwill exceed the loop bound and fall through, leaving the program in an undefined state rather than exiting gracefully. - After sorting, the screen displays sorted entries but the program falls through to the menu at line 360 without clearing the screen first, potentially leaving sort output visible behind menu text.
Variable Summary
| Variable | Purpose |
|---|---|
D$(200,32) | Main directory array, 200 × 32 characters |
D | FOR loop counter / current record index |
B$ | Name input buffer |
C$ | Phone number input buffer |
E$ | Confirmation / menu-branch input |
B | Numeric menu choice; also sort inner pointer |
G | Sort outer boundary (shrinks each pass) |
Z | Sort inner walk pointer |
Q$ | Swap temporary for sort |
A$ | Search query string |
F | Length of search query for slice bounds |
A | Search loop counter; also LPRINT loop counter |
Content
Source Code
10 REM TELEPHONE DIRECTORY
12 REM From Timex Sinclair 2068 explored entered by Izzy Goldsmith LIST Group
15 GO TO 360
20 DIM D$(200,32)
30 FOR D=1 TO 200
40 INPUT "Enter Name ";B$
90 PRINT AT 0,0;"Name: ";B$
110 INPUT "Enter telephone number ";C$
120 CLS
130 PRINT AT 0,0;B$;" ";C$
140 PRINT ''"If this is correct, press "; INVERSE 1;"ENTER"; INVERSE 0,"If incorrect, press "; FLASH 1;"'E'"; FLASH 0,"then ENTER"
150 INPUT E$: CLS
160 IF E$<>"" THEN GO TO 40
170 LET D$(D)=B$+" "+C$
180 PRINT ''"Press "; INVERSE 1;"ENTER"; INVERSE 0;" to enter next item,","or any letter, then ENTER, to","sort directory"
190 INPUT E$: CLS
200 IF E$="" THEN NEXT D
210 PRINT PAPER 2; FLASH 1;"sorting..."
216 POKE 23692,0
220 LET B=0
230 LET G=D
240 LET Z=1
250 LET B=Z+1
260 IF B>G THEN GO TO 330
270 IF D$(B)>D$(Z) THEN GO TO 290
280 LET Z=Z+1: GO TO 250
290 LET Q$=D$(Z)
300 LET D$(Z)=D$(B)
310 LET D$(B)=Q$
320 GO TO 280
330 PRINT D$(G)
340 LET G=G-1
350 IF G>0 THEN GO TO 240
360 PRINT ''"Enter one number:"
370 PRINT '"1 - To start new directory"
380 PRINT '"2 - To add new names"
390 PRINT '"3 - To search for number"
400 PRINT '"4 - To save directory"
405 PRINT '"5 - To print directory"
410 PRINT '"6 - To stop"
420 INPUT B: CLS
430 IF B=1 THEN GO TO 20
440 IF B =2 THEN NEXT D
450 IF B=3 THEN GO TO 500
460 IF B=4 THEN SAVE "DIRECTORY"
465 IF B=5 THEN FOR A=D TO 1 STEP -1: LPRINT D$(A): NEXT A
470 IF B=6 THEN STOP
480 GO TO 360
500 PRINT ''"ENTER NAME REQUIRED"
510 INPUT A$: LET F=LEN A$
520 PRINT FLASH 1; INK 1;"Searching for ";A$
530 FOR A=1 TO D
540 IF D$(A)( TO F)=A$ THEN PRINT ''D$(A)(F+1 TO ): GO TO 360
550 NEXT A
560 PRINT '"Name not found"
570 GO TO 360
9998 SAVE "Phonedir" LINE 1
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
