RANDOM ACCESS BY INDEX FILES The index file contains the key and the record number of the associated record in the main file. When the user enters the search key, the program searches for a match in the index. If we find a match to the search key in the index, we also find the location of the record in the main file. To add a record, put it in the next available location in the main file, then add its key and record number to the index file. To delete a record, just delete it from the index file, or mark it in the index file as deleted. In the second case, the next add operation could use the record location of the deleted record rather than the end of the main file. This conserves space on the disk. To change a record, find out where it is in the main file and put the new data there. The index file entry for that record remains unchanged. Here's an example using an in-RAM search of an ordered index file: 100 ' Initialization: 110 DEFINT A-Z ' use integer numbers 120 ON ERROR GOTO 800 ' if no index file 130 OPEN "0:INDEX.DO" FOR INPUT AS 1 ' open index file 140 INPUT #1,TF ' read number of entries in index file 150 DIM KY$(TF+20),RC$(TF+20) ' arrays to hold index file: key field and record number 160 C$=CHR$(44):CLS:PRINT:PRINT "Loading ..." 170 FOR N=1 TO TF ' read index file into arrays 180 INPUT #1,KY$(N),RC$(N) ' put in arrays 190 NEXT N 200 CLOSE #1:NT=TF ' initialize new top 210 OPEN "0:DATA.DO" FOR RANDOM AS 1 ' random data file 220 FIELD#1,LN$:20,FN$:20,SE$:30,CI$:15,SA$:2,ZP$:5 300 ' User's selection: 310 CLS:PRINT ' print choices 320 PRINT "1) Add a record" 330 PRINT "2) Change a record" 340 PRINT "3) Delete a record" 350 PRINT "4) Exit" 360 PRINT:PRINT "Your choice"; ' get choice 370 INPUT CH:IF CH<1 OR CH>4 THEN BEEP:GOTO 370 ' valid input? 400 ' Dispatch to routine: 410 CLS 420 ON CH GOSUB 1000,2000,3000,500 430 GOTO 310 500 ' Wrap up: 510 CLS:PRINT:CLOSE #1 ' close random file 520 PRINT "Sorting index ..." - 36 - 530 GOSUB 7000 ' sort index file 540 OT=NT ' set old top of file 550 FOR N=1 TO OT 560 IF LEFT$(KY$(N),1)=CHR$(138) THEN NT=N-1: N=OT+1 ' scan through the index for deleted records at top, set new top 570 NEXT N 580 OPEN "0:INDEX.DO" FOR OUTPUT AS 1 ' create new index file 590 PRINT #1,NT ' put new number of index entries 600 FOR N=NT 610 PRINT#1,KY$(N);C$;RC$(N) ' put it in the sequential file 620 NEXT N 630 CLOSE #1 700 ' Finished: 710 MENU 800 ' Open new index file 810 TF=0 ' initialize top of files to zero 820 ON ERROR GOTO 0 ' cancel error trap 830 RESUME 200 ' skip reading in index file 1000 ' Add a new record: 1010 GOSUB 4000 ' get new data 1020 RN=LOF(1)+1 ' new record number one more than last in file 1030 PUT#1,RN ' put it there 1040 GOSUB 5000 ' insert the key and record number in index 1050 RETURN 2000 ' Change a record: 2010 PRINT:INPUT "Last name of record to change";KE$ ' get search key 2020 RN=0:GOSUB 6000 ' search for it 2030 IF RN=0 THEN RETURN ' not found 2040 GOSUB 4000 ' get new data 2050 PUT #1,RN ' put it back in the same place 2060 IF KE$=LN$ THEN RETURN ' last name (search key) wasn't changed 2070 KY$(FK)=LN$ ' change the key 2080 RETURN 3000 ' Delete a record: 3010 PRINT:INPUT "Last name of record to delete";KE$ ' get search key 3020 RN=0:GOSUB 6000 ' search for it 3030 IF RN=0 THEN RETURN ' not found 3040 MID$(KY$(FK),1,1)=CHR$(138) ' flag index entry as deleted - 37 - 3050 PRINT "Deleted":GOSUB 8000:RETURN 4000 ' Get new data: 4010 PRINT "Enter new data:" 4020 INPUT "Last name";LN$ 4030 INPUT "First name";FN$ 4040 INPUT "Street";SE$ 4050 INPUT "City";CI$ 4060 INPUT "State";SA$ 4070 INPUT "Zip code";ZP$ 4080 RETURN 5000 ' Insert new key in index: 5010 NT=NT+1 ' increment top of index by one 5020 KY$(NT)=LN$:RC$(NT)=STR$(RN) ' put new name key and record number there 5030 RETURN 6000 ' Binary search for key in index (except newly added keys): 6010 RN=0 ' set record number to "not found" default 6020 LL=1:UL=TF ' set lower and upper search limits 6030 IF LL>UL THEN PRINT "Not found":GOSUB 8000:RETURN ' limits have crossed over, not found 6040 MD=INT((LL+UL)/2) ' calculate midpoint of search range 6050 IF KE$=KY$(MD) THEN FK=MD:RN=VAL(RC$(FK)):RETURN ' found key here 6060 IF KE$UL THEN PRINT "Not found":CLOSE#1:RETURN 1060 MD=INT((LL+UL)/2) 1070 GET#1,MD 1080 IF INSTR(1,KY$,KE$) THEN PRINT "Found": CLOSE#1:RETURN 1090 IF KE$