Advertisement
Guest User

Untitled

a guest
Oct 18th, 2017
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.11 KB | None | 0 0
  1. /**
  2.  * Implements a dictionary's functionality.
  3.  */
  4.  
  5. #include <stdio.h> // needed for printf
  6. #include <stdlib.h> // needed for malloc
  7. #include <stdbool.h> // needed for bool
  8. #include <ctype.h> //needed for isalpha, isupper, islower
  9. #include <string.h> // needed for strlen
  10.  
  11. #include "dictionary.h"
  12. #include "speller.c" // NEVER, EVER DO THIS!! .c files should not be included!! :)
  13.  
  14. // Create node data type
  15. typedef struct node
  16. {
  17.     bool is_word; // how do I default this to false??? YOU DON'T. NOT HERE.
  18.     struct node *children[27];
  19. }
  20. node;
  21.  
  22. // Declare global variables
  23. node *root = NULL; // accessed by check, load, and unload
  24. unsigned int dict_wordCount; // accessed by load, size
  25. const char *dictionary; // accessed by load, size WHY THIS? YOU DON'T NEED THIS
  26.  
  27.  
  28. /**
  29.  * Returns true if word is in dictionary else false.
  30.  */
  31.  
  32. bool check(const char *word)
  33. {
  34.     // declare variables
  35.     int gateCheck; // which gate number to check for each character in the word being spellchecked
  36.     node *cursor = root; // a cursor to move through the trie
  37.  
  38.     // for each character in the word being checked
  39.     for (int i = 0; i <= strlen(word); i++)
  40.     {
  41.         // if the character is a letter or apostrophe, translate the character's ASCII number to its corresponding gate number
  42.         if (!word[i] == 0)
  43.         {
  44.             // if the character is a capital letter
  45.             if (isupper(word[i]))
  46.             {
  47.                 gateCheck = (word[i] - 65);
  48.             }
  49.             // if the character is a miniscule letter
  50.             else if (islower(word[i]))
  51.             {
  52.                 gateCheck = (word[i] - 97);
  53.             }
  54.             // if the character is an apostrophe
  55.             else if (word[i] == 39)
  56.             {
  57.                 gateCheck = 26;
  58.             }
  59.  
  60.             // check the character's corresponding gate number
  61.             if (cursor->children[gateCheck] == NULL) // if the gate of that character is closed
  62.             {
  63.                 return false; // the word is mispelled
  64.             }
  65.             else // if the gate of that character is open
  66.             {
  67.                 *cursor = *cursor->children[gateCheck]; // move down the gate to the next character
  68.                 /*
  69.                 *******************************************************************************
  70.                 WHY ARE YOU DEREFERENCING HERE?
  71.                 YOU WANT TO MOVE THE POINTER AND NOT CHANGE THE VALUE STORED IN THE POINTER
  72.                 *******************************************************************************
  73.                 */
  74.             }
  75.         }
  76.  
  77.         // the character is a '/0' a.k.a. NUL to indicate the end of the word
  78.         else
  79.         {
  80.             if (cursor->is_word == false) // if the dictionary does not indicate the end of a word
  81.             {
  82.                 return false; // the word is mispelled
  83.             }
  84.         }
  85.     }
  86.     // the word is spelled correctly
  87.     return true;
  88. }
  89.  
  90. /**
  91.  * Loads dictionary into memory. Returns true if successful else false.
  92.  */
  93. bool load(const char *dictionary)
  94. {
  95.     // Open dictionary file
  96.     FILE *fdictionary = fopen(dictionary, "r");  // THIS DICTIONARY IS THE ARGUMENT, NOT THE GLOBAL (WHICH YOU DON'T NEED)
  97.     if (fdictionary == NULL)
  98.     {
  99.         fprintf(stderr, "Could not open %s.\n", dictionary);
  100.         return 2;
  101.     }
  102.  
  103.     // Allocate memory in the heap for the trie's first node, anchored by the root pointer
  104.     node *root = malloc(sizeof(node));  // LOOK INTO CALLOC TO ZERO INITIALIZE THE WHOLE NODE
  105.     if (root == NULL)
  106.     {
  107.         free(root);
  108.         fprintf(stderr, "Could not malloc root\n");
  109.         return 3;
  110.     }
  111.     // Set the traversal for building the trie at the root node
  112.     node *trav = root;
  113.  
  114.     // Declare variables
  115.     int gateLoad; // each character corresponds to a gate number
  116.  
  117.     // Begin constructing the trie
  118.     for (int c = getc(fdictionary); c != EOF; c = fgetc(fdictionary)) // go through entire dictionary file
  119.     {
  120.         // if the character is part of a word
  121.         if ( isalpha(c) || c == 39 )
  122.         {
  123.             // convert each character to a corresponding index number
  124.             if (isalpha(c)) // if the character is alphabetical (guaranteed to be lowercase)
  125.             {
  126.                 gateLoad = c - 97;
  127.             }
  128.             else if (c == 39) // if the character is an apostrophe
  129.             {
  130.                 gateLoad = 26;
  131.             }
  132.  
  133.             // map the character to the trie
  134.             if (trav->children[gateLoad] == NULL) // if the character's gate has not been open
  135.             {
  136.                 trav->children[gateLoad] = malloc(sizeof(node)); // create a new node
  137.                 *trav = *trav->children[gateLoad]; // move down the gate to the new node
  138.             /*
  139.             *******************************************************************************
  140.             SAME AS BEFORE, WHY ARE YOU DEREFERENCING?
  141.             ALSO VALID FOR THE ELSE RIGHT BELOW AND THE ELSE IF (C == 10) PART
  142.             *******************************************************************************
  143.             */
  144.             }
  145.             else // if the character's gate has already been open
  146.             {
  147.                 *trav = *trav->children[gateLoad]; // move down the gate to the next node
  148.             }
  149.         }
  150.         // if the character is a new break line indicating the end of a word
  151.         else if (c == 10)
  152.         {
  153.             trav->is_word = true; // indicate the word is completed
  154.             dict_wordCount++; // add one to the word counter
  155.             *trav = *root; // move back to the beginning of the trie in preparation for loading the next word
  156.         }
  157.     }
  158.     // close dictionary file
  159.     fclose(fdictionary);
  160.  
  161.     // dictionary successfully loaded
  162.     return true;
  163. }
  164.  
  165. /**
  166.  * Returns number of words in dictionary if loaded else 0 if not yet loaded.
  167.  */
  168.  
  169. unsigned int size(void)
  170. {
  171.     bool dict_loaded = load(dictionary);  // DO YOU REALLY WANT TO CALL THE LOAD FUNCTION AGAIN?
  172.     // If the dictionary was successfully loaded
  173.     if (dict_loaded == true)
  174.     {
  175.         // Return number of words loaded in the dictionary
  176.         return dict_wordCount;
  177.     }
  178.     else
  179.     // If the dictionary was not successfully loaded
  180.     {
  181.         // Return zero words loaded in the dictionary
  182.         return 0;
  183.     }
  184. }
  185.  
  186. /**
  187.  * Unloads dictionary from memory. Returns true if successful else false.
  188.  */
  189.  
  190. // unload calls freeNodes which is a function that takes in an argument for the ability to use recursion
  191. void freeNodes(node *eliminator)
  192. {
  193.     // iterate over all gates in each node's children array
  194.     for (int i = 0; i < 27; i++)
  195.     {
  196.         // starting at the root node, check all gates in current node
  197.         if (eliminator->children[i] != NULL)
  198.         {
  199.             // travel down all opened gates in current node to following node
  200.             freeNodes(eliminator->children[i]);
  201.         }
  202.     }
  203.     // base case: free the root node pointer (when nothing else is dependent on it existing)
  204.     free(eliminator);
  205. }
  206.  
  207. bool unload(void)
  208. {
  209.     // call freeNodes function, passing in root
  210.     freeNodes(root);
  211.  
  212.     // indicate when the entire trie has been eliminated
  213.     return true;
  214. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement