home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 December / simtel1292_SIMTEL_1292_Walnut_Creek.iso / msdos / pcmag / vol8n08.arc / MAKEHASH.C < prev    next >
Text File  |  1988-12-20  |  6KB  |  173 lines

  1. /*
  2.     MAKEHASH.C - Creates a data file and hash table for SRCHHASH.C 
  3.  
  4.     Copyright (C) 1988 Ziff Communications Co.
  5.     PC Magazine * Ray Duncan
  6.  
  7.     The user is prompted to enter from zero to one hundred ASCII
  8.     strings.  These strings are used to build records in the 
  9.     main data file TESTFILE.DAT and a hash table TESTFILE.HSH.
  10.  
  11.     Each record in TESTFILE.DAT is RSIZE bytes long.  The size
  12.     of the hash table is determined by the constant HASHSIZE.
  13.     The incrementing value for linear probing is HASHINCR.
  14.     All manifest constants and structures must be synchronized
  15.     with SRCHHASH.C.
  16. */
  17.  
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include <stdlib.h>
  21. #include <fcntl.h>
  22. #include <sys\types.h>
  23. #include <sys\stat.h>
  24. #include <io.h>
  25.  
  26. #define ISIZE    80                     /* max entry length */
  27. #define N_ITEMS  100                    /* max number of strings */
  28. #define RSIZE    64                     /* fixed record size */
  29. #define HASHSIZE 1024                   /* hash table size, should
  30.                                            be power of 2 */
  31. #define HASHINCR 7                      /* incrementing value for
  32.                                            linear probes of hash table */
  33.  
  34. char items[N_ITEMS * ISIZE];            /* original entries stored here */
  35.  
  36. int hashtab[HASHSIZE];                  /* hash table built here */
  37.  
  38. int getkeys(void);                      /* function prototypes */
  39. void writedata(int);
  40. void writehash(int);
  41. int hashcode(char *);
  42.  
  43. main()
  44. {
  45.     int i;                              /* number of keys entered */
  46.  
  47.     i = getkeys();                      /* get record keys from user */
  48.     writedata(i);                       /* write main data file */
  49.     writehash(i);                       /* write hash table */
  50. }
  51.  
  52. /*
  53.     Get record keys from user, leave them in array 'items',
  54.     return number of keys to caller.
  55. */
  56. int getkeys(void)
  57. {
  58.     int i, j;                           /* scratch variables */
  59.  
  60.     puts("\nEnter keys for file records...");
  61.  
  62.     i = 0;                              /* initialize string count */
  63.  
  64.     while(i < N_ITEMS)                  /* enforce maximum entries */
  65.     {
  66.         printf("%2d: ", i+1);           /* prompt user for next string */
  67.         gets(&items[ISIZE * i]);        /* read keyboard, store in array */
  68.  
  69.                                         /* last entry if empty line */
  70.         if(items[ISIZE * i] == 0) break;
  71.  
  72.         for(j = 0; j < i; j++)          /* make sure not duplicate key */
  73.         {
  74.             if(strcmp(&items[ISIZE * i], &items[ISIZE * j]) == 0)
  75.                 break;                  /* exit loop if duplicate found */
  76.         }
  77.  
  78.         if(i == j) i++;                 /* count non-duplicate strings */
  79.         else puts("Duplicate key, try again.");
  80.     }
  81.  
  82.     return (i);                         /* return no. of keys entered */
  83. }
  84.  
  85. /*
  86.     Create main data file TESTFILE.DAT, using strings stored 
  87.     in array 'items'.
  88. */
  89. void writedata(recs)
  90. {
  91.     int i = 0;                          /* scratch variable */
  92.     int fh;                             /* handle for output file */
  93.     char recbuf[RSIZE];                 /* scratch record buffer */
  94.  
  95.                                         /* create main data file */
  96.     fh = open("TESTFILE.DAT", O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, S_IWRITE);
  97.  
  98.     if(fh == -1)                        /* terminate if create failed */
  99.     {
  100.         puts("\nCan't create TESTFILE.DAT.");
  101.         exit(1);
  102.     }
  103.  
  104.     puts("\nWriting TESTFILE.DAT...");
  105.  
  106.     while(i < recs)                     /* build and write records */
  107.     {                              
  108.         memset(recbuf, 0, RSIZE);
  109.         strncpy(recbuf, &items[ISIZE * i], RSIZE);
  110.         write(fh, recbuf, RSIZE);
  111.         i++;
  112.     }
  113.  
  114.     close(fh);                          /* release file handle */
  115. }
  116.  
  117. /*
  118.     Create hash table, using strings stored in the array 'items'.
  119.     Write hash table into the file TESTFILE.HSH.
  120. */
  121. void writehash(recs)
  122. {
  123.     int i = 0, j;                       /* scratch variables */
  124.     int fh;                             /* hash table file handle */
  125.     
  126.     memset(hashtab,-1,sizeof(hashtab)); /* initialize hash table */ 
  127.  
  128.     while(i < recs)                     /* build hash table */
  129.     {                                   
  130.         j = hashcode(&items[ISIZE*i]);  /* calculate hash code */
  131.         hashtab[j] = i++;               /* put pointer into table */
  132.     }
  133.  
  134.                                         /* create hash table file */
  135.     fh = open("TESTFILE.HSH", O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, S_IWRITE);
  136.  
  137.     if(fh == -1)                        /* terminate if create failed */
  138.     {
  139.         puts("\nCan't create TESTFILE.HSH.");
  140.         exit(1);
  141.     }
  142.  
  143.     puts("\nWriting TESTFILE.HSH...");  /* write hash table */
  144.     write(fh, (char *) hashtab, sizeof(hashtab));
  145.     close(fh);                          /* release file handle */
  146. }
  147.  
  148. /*
  149.     Calculate hash code from supplied ASCII string.  Probe hash 
  150.     table and increment hashcode if necessary in order to return 
  151.     the hashcode of an unused position in the hash table.  Hash 
  152.     code is clamped to the range {0 ... HASHSIZE-1}.
  153. */
  154. int hashcode(char *kptr)
  155. {
  156.     int i, j = 0;                       /* scratch variables */
  157.  
  158.                                         /* sum characters of key */
  159.     for(i = 0; i < strlen(kptr); i++) j = (j*2) + kptr[i];
  160.     j = j & (HASHSIZE - 1);             /* clamp hash code */
  161.  
  162.     while(hashtab[j] != -1)             /* search for unused slot */
  163.     {
  164.         j += HASHINCR;                  /* increment hash code */
  165.         
  166.         if(j >= HASHSIZE)               /* wrap hashcode if necessary */
  167.             j -= HASHSIZE;
  168.     }
  169.  
  170.     return(j);                          /* return hash code */
  171. }
  172.  
  173.