home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / snip9707.zip / INDEX.C < prev    next >
C/C++ Source or Header  |  1997-07-05  |  6KB  |  179 lines

  1. /* +++Date last modified: 05-Jul-1997 */
  2.  
  3. /*
  4. **  INDEX.C
  5. **
  6. **  This is the indexing function for creating a binary file from an ASCII
  7. **  file formatted as follows:
  8. **
  9. **  Mark Corgan
  10. **  550 Foothill Rd.
  11. **  Gardnerville, NV 89410
  12. **  (702) 265-2388
  13. **  .
  14. **  Hello World
  15. **  123 Anywhere St.
  16. **  Anytown, CA 12345
  17. **  (123) 456-7890
  18. **  .
  19. **  etc...
  20. **  
  21. **  The period is what the companion LOOKUP.C looks for to indicate the end
  22. **  of record. Of course, you could have any format you like, so long as the
  23. **  first line is the information you are looking for. Also, there is no
  24. **  limit to the number of lines of infomation after the first line and
  25. **  before the period as fputs() continues until the period. Enjoy!
  26. **
  27. **  by Mark Corgan, 09-May-1993, and donated to the public domain
  28. */
  29.  
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include "errors.h"                   /* for cant()                       */
  33. #include "indxlook.h"                 /* definitions for INDEX and LOOKUP */
  34.  
  35. struct tree_node                      /* node in tree */
  36. {
  37.    struct tree_node *l_ptr, *r_ptr;   /* left and right pointers */
  38.    INDEX *data_ptr;                   /* data pointer */
  39. };
  40.  
  41. typedef struct tree_node TREE_NODE;
  42.  
  43. void        write_index(char *txtfile, char *ndxfile);
  44. void        save_tree(TREE_NODE * root, FILE *fp);
  45. TREE_NODE  *make_tree(FILE *fp, long *cnt_ptr);
  46. TREE_NODE  *insert_tree(TREE_NODE *root, INDEX *rec_ptr, long *cnt_ptr);
  47. long        bsearch_(FILE *ifp, long first, long last, char *target);
  48.  
  49. int main(int argc, char *argv[])
  50. {
  51.       if (argc != 3)
  52.       {
  53.             puts("Usage: INDEX text_file_name index_file_name\n");
  54.             puts("Note: The text file must consist of a number of records "
  55.                  "separated by lines");
  56.             puts("      containing a single period (\".\")");
  57.             return EXIT_FAILURE;
  58.       }
  59.       write_index(argv[1], argv[2]);
  60.       return EXIT_SUCCESS;
  61. }
  62.  
  63. void write_index(char *txtfile, char *ndxfile)
  64. {
  65.       FILE *afp, *ifp;                    /* types of files       */
  66.       TREE_NODE *root;                    /* index tree           */
  67.       static INDEX header = {"!", 0};     /* dummy header node    */
  68.  
  69.       afp = cant(txtfile, "r");
  70.       if ((root = make_tree(afp, &header.pos)) != NULL)
  71.       {
  72.             ifp = cant(ndxfile, "wb");
  73.             fwrite((char *) &header, sizeof(header), 1, ifp);
  74.             save_tree(root, ifp);
  75.             fclose(ifp);
  76.             printf("\n%ld records\n", header.pos);
  77.       }
  78.       fclose(afp);
  79. }
  80.  
  81. /*
  82. ** Make index tree
  83. */
  84.  
  85. TREE_NODE *make_tree(FILE *fp,            /* file                 */
  86.                      long *cnt_ptr)       /* count of records     */
  87. {
  88.       TREE_NODE *root = NULL, *temp_ptr;  /* add node to tree     */
  89.       char line[MAX_LINE];                /* next line            */
  90.       long start_pos = 0;
  91.       INDEX *next_ptr;                    /* next key, pos pair   */
  92.       /* starting with new record */
  93.       Boolean_T new_record = True_, have_mem = True_;
  94.  
  95.       *cnt_ptr = 0;
  96.       while (start_pos = ftell(fp), have_mem && fgets(line,sizeof(line), fp))
  97.       {
  98.             if (new_record)
  99.             {
  100.                   if ((next_ptr = (INDEX *) malloc(sizeof(INDEX))) != NULL)
  101.                   {
  102.                         strncpy(next_ptr->key, line, MAX_KEY);
  103.  
  104.                         next_ptr->pos = start_pos;
  105.                         temp_ptr      = insert_tree(root, next_ptr, cnt_ptr);
  106.  
  107.                         if (temp_ptr)
  108.                               root = temp_ptr;
  109.                   }
  110.                   have_mem = next_ptr && temp_ptr;
  111.             }
  112.             new_record = strcmp(line, END_REC) == 0;
  113.       }
  114.       if (!have_mem)
  115.             fprintf(stderr, "Out of memory. Key: %s\n", line);
  116.  
  117.       return root;
  118. }
  119.  
  120. /*
  121. ** Save the index tree to a file
  122. */
  123.  
  124. void save_tree(TREE_NODE *root, FILE *fp)
  125. {
  126.       if (root)
  127.       {
  128.             save_tree(root->l_ptr, fp);
  129.             fwrite(root->data_ptr, sizeof(INDEX), 1, fp);
  130.             save_tree(root->r_ptr, fp);
  131.       }
  132. }
  133.  
  134. /*
  135. ** Add record to tree
  136. */
  137.  
  138. TREE_NODE *insert_tree(TREE_NODE *root,         /* pointer to tree      */
  139.                        INDEX *rec_ptr,          /* record to install    */
  140.                        long *cnt_ptr)           /* nodes in tree        */
  141.  
  142. {
  143.       if (root)
  144.       {
  145.             int cmp = strncmp(rec_ptr->key, root->data_ptr->key, MAX_KEY);
  146.  
  147.             if (cmp < 0)                        /* left side?           */
  148.                   root->l_ptr = insert_tree(root->l_ptr, rec_ptr, cnt_ptr);
  149.             else if (cmp > 0)                   /* right side           */
  150.                   root->r_ptr = insert_tree(root->r_ptr, rec_ptr, cnt_ptr);
  151.             else  fprintf(stderr, "Duplicate key: %s\n", rec_ptr->key);
  152.       }
  153.       else if (root = (TREE_NODE *) malloc(sizeof(TREE_NODE)), root)
  154.       {
  155.             root->data_ptr = rec_ptr;
  156.             root->l_ptr = root->r_ptr = NULL;
  157.             (*cnt_ptr)++;
  158.       }
  159.       return root;
  160. }
  161.  
  162. long bsearch_(FILE *ifp, long first, long last, char *target)
  163. {
  164.       long pos, mid =(first + last) / 2;
  165.       INDEX next;
  166.       int cmp;
  167.  
  168.       if (mid < first || fseek(ifp, mid * sizeof(INDEX), 0) != 0 ||
  169.           fread((char *) &next, sizeof(INDEX), 1, ifp) == 0)
  170.       {
  171.             pos = -1;
  172.       }
  173.       else  pos = ((cmp = strncmp(target, next.key, MAX_KEY)) == 0) ?
  174.                   next.pos :
  175.                   ((cmp < 0) ? bsearch_(ifp, first, mid - 1, target)
  176.                              : bsearch_(ifp, mid + 1, last, target));
  177.       return pos;
  178. }
  179.