--- title: "Telephone Directory" id: 54578 type: "computer_media" slug: "phone-directory" url: "http://localhost/computer_media/phone-directory/" markdown_url: "http://localhost/computer_media/phone-directory.md" published_at: "2024-06-02T17:49:14+00:00" modified_at: "2026-03-30T21:45:57+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/06/SCR-20240714-eyjk.png" excerpt: "A full-featured telephone directory application with interactive entry, alphabetical bubble sort, substring search, and hardcopy printing — all in BASIC." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 2068" slug: "ts2068" taxonomy: "post_tag" url: "http://localhost/tag/ts2068/" model: - name: "Timex/Sinclair 2068" slug: "ts-2068" taxonomy: "model" url: "http://localhost/model/ts-2068/" indiv: - name: "Tim Hartnell" slug: "tim-hartnell" taxonomy: "indiv" url: "http://localhost/indiv/tim-hartnell/" genre: - name: "Database" slug: "database" taxonomy: "genre" url: "http://localhost/type/database/" - name: "Home" slug: "home" taxonomy: "genre" url: "http://localhost/type/home/" media_contents: - id: 51214 title: "CATS Library Tape 8" type: "computer_media" url: "http://localhost/computer_media/cats-library-tape-8/" media_type: "Program" programmers: - name: "Tim Hartnell" slug: "tim-hartnell" taxonomy: "indiv" url: "http://localhost/indiv/tim-hartnell/" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/06/SCR-20240714-eyjk.png" related_content: - id: 20969 title: "The Timex Sinclair 2068 Explored" type: "book" url: "http://localhost/book/the-timex-sinclair-2068-explored/" media_type_tags: "Database, Home" --- # Telephone Directory 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: 1. **Lines 20–210:** Array initialization and interactive data entry loop 2. **Lines 220–350:** Bubble sort routine, triggered when the user exits the entry loop 3. **Lines 360–480:** Main menu dispatcher 4. **Lines 500–570:** Name search routine 5. **Line 9998:**`SAVE` with 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 `FOR` loop variable `D` as both counter and record-count sentinel. - Prefix-match search using open-ended slice notation `D$(A)(TO F)` and `D$(A)(F+1 TO )`. - `POKE 23692,0` to suppress scroll prompts during bulk screen output. - `INVERSE 1` and `FLASH 1` used inline within `PRINT` statements 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 `LPRINT` loop at line 465 iterates from `D 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 in `D$()` but the printout walks it backwards. - There is no `LOAD` option in the menu, so a previously saved “DIRECTORY” file cannot be retrieved within the running program. - The entry loop uses `FOR D=1 TO 200` but the array is dimensioned to 200; if all 200 slots are filled and the user presses ENTER to continue, `NEXT D` will 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 | ## 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 ```