12e9dd93eSCaroline Tice //===-- dictionary.c ---------------------------------------------*- C -*-===//
22e9dd93eSCaroline Tice //
3*2946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*2946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
5*2946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62e9dd93eSCaroline Tice //
72e9dd93eSCaroline Tice //===---------------------------------------------------------------------===//
82e9dd93eSCaroline Tice #include <ctype.h>
9b9c1b51eSKate Stone #include <stdio.h>
10b9c1b51eSKate Stone #include <stdlib.h>
112e9dd93eSCaroline Tice #include <string.h>
122e9dd93eSCaroline Tice 
13b9c1b51eSKate Stone typedef struct tree_node {
142e9dd93eSCaroline Tice   const char *word;
152e9dd93eSCaroline Tice   struct tree_node *left;
162e9dd93eSCaroline Tice   struct tree_node *right;
172e9dd93eSCaroline Tice } tree_node;
182e9dd93eSCaroline Tice 
192e9dd93eSCaroline Tice /* Given a char*, returns a substring that starts at the first
202e9dd93eSCaroline Tice    alphabet character and ends at the last alphabet character, i.e. it
212e9dd93eSCaroline Tice    strips off beginning or ending quotes, punctuation, etc. */
222e9dd93eSCaroline Tice 
strip(char ** word)23b9c1b51eSKate Stone char *strip(char **word) {
242e9dd93eSCaroline Tice   char *start = *word;
252e9dd93eSCaroline Tice   int len = strlen(start);
262e9dd93eSCaroline Tice   char *end = start + len - 1;
272e9dd93eSCaroline Tice 
282e9dd93eSCaroline Tice   while ((start < end) && (!isalpha(start[0])))
292e9dd93eSCaroline Tice     start++;
302e9dd93eSCaroline Tice 
312e9dd93eSCaroline Tice   while ((end > start) && (!isalpha(end[0])))
322e9dd93eSCaroline Tice     end--;
332e9dd93eSCaroline Tice 
342e9dd93eSCaroline Tice   if (start > end)
352e9dd93eSCaroline Tice     return NULL;
362e9dd93eSCaroline Tice 
372e9dd93eSCaroline Tice   end[1] = '\0';
382e9dd93eSCaroline Tice   *word = start;
392e9dd93eSCaroline Tice 
402e9dd93eSCaroline Tice   return start;
412e9dd93eSCaroline Tice }
422e9dd93eSCaroline Tice 
432e9dd93eSCaroline Tice /* Given a binary search tree (sorted alphabetically by the word at
442e9dd93eSCaroline Tice    each node), and a new word, inserts the word at the appropriate
452e9dd93eSCaroline Tice    place in the tree.  */
462e9dd93eSCaroline Tice 
insert(tree_node * root,char * word)47b9c1b51eSKate Stone void insert(tree_node *root, char *word) {
482e9dd93eSCaroline Tice   if (root == NULL)
492e9dd93eSCaroline Tice     return;
502e9dd93eSCaroline Tice 
512e9dd93eSCaroline Tice   int compare_value = strcmp(word, root->word);
522e9dd93eSCaroline Tice 
532e9dd93eSCaroline Tice   if (compare_value == 0)
542e9dd93eSCaroline Tice     return;
552e9dd93eSCaroline Tice 
56b9c1b51eSKate Stone   if (compare_value < 0) {
572e9dd93eSCaroline Tice     if (root->left != NULL)
582e9dd93eSCaroline Tice       insert(root->left, word);
59b9c1b51eSKate Stone     else {
602e9dd93eSCaroline Tice       tree_node *new_node = (tree_node *)malloc(sizeof(tree_node));
612e9dd93eSCaroline Tice       new_node->word = strdup(word);
622e9dd93eSCaroline Tice       new_node->left = NULL;
632e9dd93eSCaroline Tice       new_node->right = NULL;
642e9dd93eSCaroline Tice       root->left = new_node;
652e9dd93eSCaroline Tice     }
66b9c1b51eSKate Stone   } else {
672e9dd93eSCaroline Tice     if (root->right != NULL)
682e9dd93eSCaroline Tice       insert(root->right, word);
69b9c1b51eSKate Stone     else {
702e9dd93eSCaroline Tice       tree_node *new_node = (tree_node *)malloc(sizeof(tree_node));
712e9dd93eSCaroline Tice       new_node->word = strdup(word);
722e9dd93eSCaroline Tice       new_node->left = NULL;
732e9dd93eSCaroline Tice       new_node->right = NULL;
742e9dd93eSCaroline Tice       root->right = new_node;
752e9dd93eSCaroline Tice     }
762e9dd93eSCaroline Tice   }
772e9dd93eSCaroline Tice }
782e9dd93eSCaroline Tice 
792e9dd93eSCaroline Tice /* Read in a text file and storea all the words from the file in a
802e9dd93eSCaroline Tice    binary search tree.  */
812e9dd93eSCaroline Tice 
populate_dictionary(tree_node ** dictionary,char * filename)82b9c1b51eSKate Stone void populate_dictionary(tree_node **dictionary, char *filename) {
832e9dd93eSCaroline Tice   FILE *in_file;
842e9dd93eSCaroline Tice   char word[1024];
852e9dd93eSCaroline Tice 
862e9dd93eSCaroline Tice   in_file = fopen(filename, "r");
87b9c1b51eSKate Stone   if (in_file) {
88b9c1b51eSKate Stone     while (fscanf(in_file, "%s", word) == 1) {
892e9dd93eSCaroline Tice       char *new_word = (strdup(word));
902e9dd93eSCaroline Tice       new_word = strip(&new_word);
91b9c1b51eSKate Stone       if (*dictionary == NULL) {
922e9dd93eSCaroline Tice         tree_node *new_node = (tree_node *)malloc(sizeof(tree_node));
932e9dd93eSCaroline Tice         new_node->word = new_word;
942e9dd93eSCaroline Tice         new_node->left = NULL;
952e9dd93eSCaroline Tice         new_node->right = NULL;
962e9dd93eSCaroline Tice         *dictionary = new_node;
97b9c1b51eSKate Stone       } else
982e9dd93eSCaroline Tice         insert(*dictionary, new_word);
992e9dd93eSCaroline Tice     }
1002e9dd93eSCaroline Tice   }
1012e9dd93eSCaroline Tice }
1022e9dd93eSCaroline Tice 
1032e9dd93eSCaroline Tice /* Given a binary search tree and a word, search for the word
1042e9dd93eSCaroline Tice    in the binary search tree.  */
1052e9dd93eSCaroline Tice 
find_word(tree_node * dictionary,char * word)106b9c1b51eSKate Stone int find_word(tree_node *dictionary, char *word) {
1072e9dd93eSCaroline Tice   if (!word || !dictionary)
1082e9dd93eSCaroline Tice     return 0;
1092e9dd93eSCaroline Tice 
1102e9dd93eSCaroline Tice   int compare_value = strcmp(word, dictionary->word);
1112e9dd93eSCaroline Tice 
1122e9dd93eSCaroline Tice   if (compare_value == 0)
1132e9dd93eSCaroline Tice     return 1;
1142e9dd93eSCaroline Tice   else if (compare_value < 0)
1152e9dd93eSCaroline Tice     return find_word(dictionary->left, word);
1162e9dd93eSCaroline Tice   else
1172e9dd93eSCaroline Tice     return find_word(dictionary->right, word);
1182e9dd93eSCaroline Tice }
1192e9dd93eSCaroline Tice 
1202e9dd93eSCaroline Tice /* Print out the words in the binary search tree, in sorted order.  */
1212e9dd93eSCaroline Tice 
print_tree(tree_node * dictionary)122b9c1b51eSKate Stone void print_tree(tree_node *dictionary) {
1232e9dd93eSCaroline Tice   if (!dictionary)
1242e9dd93eSCaroline Tice     return;
1252e9dd93eSCaroline Tice 
1262e9dd93eSCaroline Tice   if (dictionary->left)
1272e9dd93eSCaroline Tice     print_tree(dictionary->left);
1282e9dd93eSCaroline Tice 
1292e9dd93eSCaroline Tice   printf("%s\n", dictionary->word);
1302e9dd93eSCaroline Tice 
1312e9dd93eSCaroline Tice   if (dictionary->right)
1322e9dd93eSCaroline Tice     print_tree(dictionary->right);
1332e9dd93eSCaroline Tice }
1342e9dd93eSCaroline Tice 
main(int argc,char ** argv)135b9c1b51eSKate Stone int main(int argc, char **argv) {
1362e9dd93eSCaroline Tice   tree_node *dictionary = NULL;
1372e9dd93eSCaroline Tice   char buffer[1024];
1382e9dd93eSCaroline Tice   char *filename;
1392e9dd93eSCaroline Tice   int done = 0;
1402e9dd93eSCaroline Tice 
1412e9dd93eSCaroline Tice   if (argc == 2)
1422e9dd93eSCaroline Tice     filename = argv[1];
1432e9dd93eSCaroline Tice 
1442e9dd93eSCaroline Tice   if (!filename)
1452e9dd93eSCaroline Tice     return -1;
1462e9dd93eSCaroline Tice 
1472e9dd93eSCaroline Tice   populate_dictionary(&dictionary, filename);
1482e9dd93eSCaroline Tice   fprintf(stdout, "Dictionary loaded.\nEnter search word: ");
149b9c1b51eSKate Stone   while (!done && fgets(buffer, sizeof(buffer), stdin)) {
1502e9dd93eSCaroline Tice     char *word = buffer;
1512e9dd93eSCaroline Tice     int len = strlen(word);
1522e9dd93eSCaroline Tice     int i;
1532e9dd93eSCaroline Tice 
1542e9dd93eSCaroline Tice     for (i = 0; i < len; ++i)
1552e9dd93eSCaroline Tice       word[i] = tolower(word[i]);
1562e9dd93eSCaroline Tice 
157b9c1b51eSKate Stone     if ((len > 0) && (word[len - 1] == '\n')) {
1582e9dd93eSCaroline Tice       word[len - 1] = '\0';
1592e9dd93eSCaroline Tice       len = len - 1;
1602e9dd93eSCaroline Tice     }
1612e9dd93eSCaroline Tice 
1622e9dd93eSCaroline Tice     if (find_word(dictionary, word))
1632e9dd93eSCaroline Tice       fprintf(stdout, "Yes!\n");
1642e9dd93eSCaroline Tice     else
1652e9dd93eSCaroline Tice       fprintf(stdout, "No!\n");
1662e9dd93eSCaroline Tice 
1672e9dd93eSCaroline Tice     fprintf(stdout, "Enter search word: ");
1682e9dd93eSCaroline Tice   }
1692e9dd93eSCaroline Tice 
1702e9dd93eSCaroline Tice   fprintf(stdout, "\n");
1712e9dd93eSCaroline Tice   return 0;
1722e9dd93eSCaroline Tice }
173