Tutorial 041 A Novel Phonebook Program
This program makes use of the techniques explained in Tutorials 34 to 40
and combines them to give an unusual but very useful alphabetical index for
all words used in a phonebook text file, which enables phone numbers to be
obtained by first name, surname or by other added words.
Thus a record such as : William Cleaver (Butcher) 858585, would be
automatically indexed alphabetically under Butcher, Cleaver and William.
I recently decided to sort out our battered , thirty-year-old, Telephone
Index Book, which had numerous deletions, corrections and appendices. One
doesn't want to have turn on the computer especially to look up a telephone
number so I typed the entries into two separate Word files ("people"
and "services") alphabetically by Surname in the format shown above and printed
out a copy for each of the telephones in the house. There were four A4 pages
for the "names" and one for the "services". Much easier to use than the battered
old index book with its cover hanging off!
To make more use of the information and to be able to index it more thoroughly,
I first saved the data from the Word files as text files for
examination by the (slightly modified ) program from Tutorial 34 (Virgil's
Vocab). This latter ignores the numbers themselves and sorts all the other
words into alphabetical order. By tagging each word with its "record number"
its then easy to retrieve the required record containing the full name and
telephone number.
I'm wouldn't be fair to publish all my phone contacts(!) so here is a smaller
fictitious equivalent of a suitable text file which you can Select/copy/paste
into Notepad and save (in the same directory as the program for easiest
loading) in order to try out the program...
Herbertina Broadcats 939393
Desmond Cartwrong-Bilgewater 121212
Henry Centiheit 292929
Francis Dunin 919191
Catherine Emblemish 191919
Ziggi Florbin 181818
Xeno Googlebot 717171
Wilfred Haagbod 171717.... 676767
Violet Ioblast 161616
Ursula Jumbles 151515
Telula Kickback 141414
Sergei Lobit 313131
Rowena Moreless 131313
Quentin Nirdlewright 989898
Patricia Orother 898989
Orlando Pinchback 878787
Norris Quilt 787878
Miranda Ripieno 767676
Lucinda Supergras 676767
Kevin Tigglethwaite 656565
Janet Ululat 565656
Ian Van-der-Crunch 545454
Gillian Wiffledown 454545
Ethelred Xylemtwistle 343434
Bertha Yodle-Bootstrap 242424
Alvin Ziggenbaum 323232
ABCD-Garage Garage 393939
Bert Renticle (Plumber) 494949
Makeurite (Doctor) 949494
NatEast (Bank) 353535
Frybynight (Fish-and-Chips) 393939
Which gives a single screen of output :
Press <SPACE> to choose a phone directory
ABCD-Garage(27) Alvin(1) Bank(30) Bert(28) Bertha(2) Broadcats(26)
Cartwrong-Bilgewater(22) Catherine(23) Centiheit(25) Desmond(22) Doctor(29)
Dunin(24) Emblemish(23) Ethelred(3) Fish-and-Chips(31) Florbin(21) Francis(24)
Frybynight(31) Garage(27) Gillian(4) Googlebot(20) Haagbod(19) Henry(25)
Herbertina(26) Ian(5) Ioblast(18) Janet(6) Jumbles(17) Kevin(7) Kickback(16)
Lobit(15) Lucinda(8) Makeurite(29) Miranda(9) Moreless(14) NatEast(30)
Nirdlewright(13) Norris(10) Orlando(11) Orother(12) Patricia(12) Pinchback(11)
Plumber(28) Quentin(13) Quilt(10) Renticle(28) Ripieno(9) Rowena(14) Sergei(15)
Supergras(8) Telula(16) Tigglethwaite(7) Ululat(6) Ursula(17) Van-der-Crunch(5)
Violet(18) Wiffledown(4) Wilfred(19) Xeno(20) Xylemtwistle(3)
Yodle-Bootstrap(2) Ziggenbaum(1) Ziggi(21)
Input the record number to see the record : 31
Frybynight (Fish-and-Chips) 393939
Press <SPACE> to find another phone number...
Here you can see that although I could not remember
the name of the chip shop, the fish-and-chip entry enabled me to locate
the entry quite easily in the alphabetic list of all the words present. First
names are as easy to find as surnames in this novel directory!
N.B. I've used hyphens to avoid some phrases being split, as we allowed
for hyphens to be retained in the Virgil's Vocab program. Other examples
are ABCD-Garage ( remember the Association of Bent Car Delears?), and Van-der-Cruch,
which may not have the hyphens in practice...
Listing :
MODE8
REM : Converts a phone list text file
REM : whose lines are in the form...
REM : <first name> <space> <
surname > <space> <phone number(s)>
REM : Richard Weston, 10th July 2003
MODE 8
rec=1
t=1000 :REM word capacity
DIM word$(t),rank(t)
COLOUR1
PRINT'" Press <SPACE> to choose a phone
directory"'
G=GET
OFF
:
DIM of% 75, ff% 18, fn% 255
!of% = 76
of%!4 = @hwnd%
of%!12 = ff%
of%!28 = fn%
of%!32 = 256
of%!52 = 6
$ff% = "Text Files"+CHR$0+"*.txt"+CHR$0+CHR$0
:
SYS "GetOpenFileName", of% TO result%
IF result% filename$ = FNnulterm$(fn%)
COLOUR2
:
fnum=OPENIN filename$
IF fnum=0 THEN PRINT "No ";filename$;" data":
END
:
n=0
COLOUR7
REPEAT
finished=FALSE
word$=""
REPEAT
temp=BGET#fnum :REM
Read byte
PROCprocess
UNTIL finished
IF LEN(word$)>1 THEN
word$=word$+"(" +
STR$(rec) + ")"
n+=1
word$(n)=word$
ENDIF
UNTIL EOF#fnum
CLOSE#fnum
:
newword=0
COLOUR7
:
PROCsort
:
COLOUR11
REM PRINT'"Press <SHIFT> to scroll
down"'
COLOUR7
REPEAT
FOR i=t-1 TO 1 STEP -1
pos=POS:L=LEN(word$(rank(i)))
:
PROCcheck_already_met
:
IF alreadymet=FALSE
THEN
newword+=1
IF L
< (80-pos) THEN
PRINTword$(rank(i))+" ";
ELSE
IF VPOS>27 THEN
COLOUR1:PRINT:PRINT"Press <SPACE>":G=GET:CLS:COLOUR7
*FX21,0
ENDIF
PRINT'word$(rank(i))+" ";
ENDIF
ENDIF
NEXT i
PRINT'
COLOUR9
ON:COLOUR6
INPUT'"Input the record number
to see the record : "r
PROCfindrecord
COLOUR2
PRINT'" Press <SPACE> to
find another phone number..."
COLOUR7
G=GET
CLS
UNTIL FALSE
END
:
DEF FNnulterm$(P%)
LOCAL A$
WHILE ?P% <> 0
A$ += CHR$?P%
P% += 1
ENDWHILE
= A$
:
DEF PROCprocess
IF temp>64 AND temp<91 THEN
word$+=CHR$(temp)
ENDIF
:
IF temp>96 AND temp<123 THEN
word$+=CHR$(temp)
ENDIF
:
IF temp=45 THEN word$+=CHR$(temp)
REM^ hyphen
IF temp=10 THEN
finished=TRUE
rec+=1
ENDIF
IF temp>31 AND temp<65 THEN finished=TRUE
IF temp=45 THEN finished=FALSE
IF temp>90 AND temp<97 THEN finished=TRUE
IF temp>122 THEN finished=TRUE
ENDPROC
:
:
DEF PROCcheck_already_met
alreadymet=FALSE
IF word$(rank(i))=word$(rank(i+1)) THEN
alreadymet=TRUE
ENDIF
ENDPROC
:
DEF PROCsort:LOCAL I
FOR I = 1 TO t
rank(I)=I
NEXT
PROCquicksort(1,t)
ENDPROC
:
DEF PROCquicksort(low,high)
LOCAL left,right,it,dummy
left=low:right=high
it$=word$(rank((low+high)DIV 2))
REPEAT
IF word$(rank(left))>it$ THEN
REPEAT left=left+1
UNTIL word$(rank(left))<=it$
ENDIF
IF word$(rank(right))<it$
THEN
REPEAT right=right-1
UNTIL word$(rank(right))>=it$
ENDIF
IF left<=right THEN
dummy=rank(left)
rank(left)=rank(right)
rank(right)=dummy
left=left+1
right=right-1
ENDIF
UNTIL left>right
IF right>low THEN PROCquicksort(low,right)
IF left<high THEN PROCquicksort(left,high)
ENDPROC
:
DEF PROCfindrecord
fnum=OPENIN filename$
IF fnum=0 THEN PRINT "No ";filename$;" data":
END
rec=0
REPEAT
rec$=""
REPEAT
temp=BGET#fnum :REM
Read byte
rec$=rec$+CHR$(temp)
UNTIL temp=10
rec+=1
UNTIL rec=r
COLOUR7
PRINT'TAB(3)rec$
CLOSE#fnum
ENDPROC
Annotated Listing :
MODE8
REM : Converts a phone list text file
REM : whose lines are in the form...
REM : <first name> <space> <
surname > <space> <phone number(s)>
REM : Richard Weston, 10th July 2003
MODE 8
rec=1 *** record number ***
t=1000 : REM word capacity ***increase this
if you have a big enough directory ***
DIM word$(t),rank(t)
COLOUR1
PRINT'" Press <SPACE> to choose a phone
directory"'
G=GET
OFF
:
DIM of% 75, ff% 18, fn% 255 *** Here it is
again *** File loading routine *********
!of% = 76
of%!4 = @hwnd%
of%!12 = ff%
of%!28 = fn%
of%!32 = 256
of%!52 = 6
$ff% = "Text Files"+CHR$0+"*.txt"+CHR$0+CHR$0
:
SYS "GetOpenFileName", of% TO result%
IF result% filename$ = FNnulterm$(fn%)
COLOUR7
COLOUR2
:
fnum=OPENIN filename$
IF fnum=0 THEN PRINT "No ";filename$;" data":
END ************************** end
:
n=0 *** number of words ***
COLOUR7
REPEAT ******************** word identification
- see earlier programs ***********
finished=FALSE
word$=""
REPEAT
temp=BGET#fnum :REM
Read byte
PROCprocess
UNTIL finished
IF LEN(word$)>1 THEN
word$=word$+"(" +
STR$(rec) + ")" **** here's where we add the record number tag to the word
***
n+=1
word$(n)=word$ ****
store the word and tag away ready for sorting ****
ENDIF
UNTIL EOF#fnum
CLOSE#fnum
:
newword=0
COLOUR7
:
PROCsort ******************* as previously
described ********************
:
COLOUR7
REPEAT
FOR i=t-1 TO 1 STEP -1
pos=POS:L=LEN(word$(rank(i)))
:
PROCcheck_already_met
:
IF alreadymet=FALSE
THEN
newword+=1
IF L
< (80-pos) THEN
PRINTword$(rank(i))+" ";
ELSE
IF VPOS>27 THEN ************ need to start a new line *************
COLOUR1:PRINT:PRINT"Press <SPACE>":G=GET:CLS:COLOUR7 **** To get next
screensworth ****
*FX21,0 ********* flush the buffers to avoid multiple inputs ************
ENDIF
PRINT'word$(rank(i))+" ";
ENDIF
ENDIF
NEXT i
PRINT'
COLOUR9
ON:COLOUR6
INPUT'"Input the record number
to see the record : "r
PROCfindrecord
COLOUR2
PRINT'" Press <SPACE> to
find another phone number..."
COLOUR7
G=GET
CLS
UNTIL FALSE
END
:
DEF FNnulterm$(P%)
LOCAL A$
WHILE ?P% <> 0
A$ += CHR$?P%
P% += 1
ENDWHILE
= A$
:
DEF PROCprocess *********************
IF temp>64 AND temp<91 THEN
word$+=CHR$(temp)
ENDIF
:
IF temp>96 AND temp<123 THEN
word$+=CHR$(temp)
ENDIF
:
IF temp=45 THEN word$+=CHR$(temp)
REM^ hyphen
IF temp=10 THEN
finished=TRUE
rec+=1************** NEW! counts
the number of records
ENDIF
IF temp>31 AND temp<65 THEN finished=TRUE
IF temp=45 THEN finished=FALSE
IF temp>90 AND temp<97 THEN finished=TRUE
IF temp>122 THEN finished=TRUE
ENDPROC
:
:
DEF PROCcheck_already_met ********* unlikely
to be needed here ***************
alreadymet=FALSE
IF word$(rank(i))=word$(rank(i+1)) THEN
alreadymet=TRUE
ENDIF
ENDPROC
:
DEF PROCsort:LOCAL I
FOR I = 1 TO t
rank(I)=I
NEXT
PROCquicksort(1,t)
ENDPROC
:
DEF PROCquicksort(low,high)
LOCAL left,right,it,dummy
left=low:right=high
it$=word$(rank((low+high)DIV 2))
REPEAT
IF word$(rank(left))>it$ THEN
REPEAT left=left+1
UNTIL word$(rank(left))<=it$
ENDIF
IF word$(rank(right))<it$
THEN
REPEAT right=right-1
UNTIL word$(rank(right))>=it$
ENDIF
IF left<=right THEN
dummy=rank(left)
rank(left)=rank(right)
rank(right)=dummy
left=left+1
right=right-1
ENDIF
UNTIL left>right
IF right>low THEN PROCquicksort(low,right)
IF left<high THEN PROCquicksort(left,high)
ENDPROC
:
DEF PROCfindrecord ****************** NEW!
re-reads the file to find the record requested
fnum=OPENIN filename$
IF fnum=0 THEN PRINT "No ";filename$;" data":
END
rec=0
REPEAT
rec$=""
REPEAT
temp=BGET#fnum :REM
Read byte
rec$=rec$+CHR$(temp)
UNTIL temp=10
rec+=1
UNTIL rec=r ******************* GOT IT!
COLOUR7
PRINT'TAB(3)rec$ *************** now print
it!!
CLOSE#fnum
ENDPROC
Next Tutorial
Richard Weston's Homepage