/* SRCHNIF.C Searches file previously created by MAKENIF.EXE Copyright (c) 1989 Ziff Communications Co. PC Magazine * Ray Duncan The user is prompted to enter a search key. The first 8 characters of the key are used to search TESTFILE.DAT, using both the sequential and binary search algorithms. The success or failure of the search is reported along with the number of records inspected by each method. Each record in TESTFILE.DAT is RSIZE bytes long. Bytes 0 to (KSIZE-1) of the record are the ASCII key for searches by SRCHNIF.C. Bytes KSIZE to (RSIZE-1) of the record are initialized to zero and are not used. RSIZE and KSIZE must be kept synchronized with their definitions in MAKENIF.C. */ #include #include #include #include #include #include #include #define RSIZE 64 /* fixed record size */ #define KSIZE 8 /* maximum key length */ static int inspected; /* records inspected counter */ main() { int i, j; /* some scratch variables */ int fh; /* handle for data file */ long fsize; /* size of file in bytes */ int frecs; /* number of records in file */ char key[80]; /* key entered by user */ char rec[RSIZE]; /* scratch record buffer */ /* open our data file */ fh = open("TESTFILE.DAT", O_RDONLY | O_BINARY); if(fh == -1) /* terminate if open failed */ { puts("\nCan't find TESTFILE.DAT."); exit(1); } fsize = lseek(fh, 0L, SEEK_END); /* find file size */ frecs = fsize / RSIZE; /* calculate number of records */ printf("\nTESTFILE.DAT contains %ld bytes, %d records.", fsize, frecs); while(1) { printf("\n\nEnter key: "); /* prompt user and */ gets(key); /* input record key */ if(key[0] == 0) break; /* terminate if empty line */ if(strlen(key) > KSIZE) printf("\nWarning: key truncated to %d characters.", KSIZE); inspected = 0; /* reset record counter */ /* perform sequential search */ /* and display results */ printf("\nSequential search result: "); if((i = seqsearch(fh, key)) == -1) printf("record not found,"); else printf("record number is %d,", i); printf(" %d records inspected.", inspected); inspected = 0; /* reset record counter */ /* perform binary search */ /* and display results */ printf("\nBinary search result: "); if((i = binsearch(fh, key, 0, frecs-1)) == -1) printf("record not found,"); else printf("record number is %d,", i); printf(" %d records inspected.", inspected); } close(fh); /* release file handle */ } /* Search the file sequentially to match the specified key. Called with a file handle and key address. Returns the record number if match found, or -1 to indicate no match. */ int seqsearch(int fh, char *kptr) { int i; /* scratch variable */ char fbuff[RSIZE]; /* file record buffer */ lseek(fh, 0L, SEEK_SET); /* rewind to start of file */ while(read(fh, fbuff, RSIZE) != 0) /* do until end of file found */ { inspected++; /* count records inspected */ i = strncmp(kptr, fbuff, KSIZE); /* compare keys */ if(i == 0) return(inspected-1); /* if matched, return record no. */ else if(i < 0) break; /* if record absent, end search */ } return(-1); /* no match, return -1 */ } /* Binary search the file to match the specified key. Called with a file handle, key address, and the first and last record numbers of the file segment being inspected. Returns the record number if match found, or -1 to indicate no match. */ int binsearch(int fh, char *kptr, int left, int right) { int i, j; /* scratch variables */ char fbuff[RSIZE]; /* file record buffer */ if(left > right) return(-1); /* end search if record absent */ i = (left + right) / 2; /* calculate record number */ inspected++; /* count records inspected */ lseek(fh, (long) (i * RSIZE), SEEK_SET); read(fh, fbuff, RSIZE); /* read the record */ j = strncmp(kptr, fbuff, KSIZE); /* compare keys */ if(j == 0) return(i); /* if matched, return record no. */ /* otherwise bisect file, recurse to inspect next record */ if(j < 0) binsearch(fh, kptr, left, i-1); else binsearch(fh, kptr, i+1, right); }