Pset 5 Speller Trie在卸载时出现分段故障

时间:2017-09-07 14:44:18

标签: c null segmentation-fault cs50

我使用trie为dictionary.c实现了加载,检查和卸载,我遇到了分段错误。错误发生在加载函数内部,或者更准确地说,发生在名为un_node的函数内部,这是我在卸载时调用的递归函数。运行debug50时弹出行if(cursor -> children[a] != NULL)。虽然我没有将我的root / head节点作为全局(我刚刚编写node *root;)来malloc,但是现在在load function中分配的内存是不是?

我确实检查了我是否将next_node的每个子节点都指向null并将它们锁定在它们之后。

关于un_node函数,我不确定我是否应该在for循环内部或在for循环外部free(cursor); return;

    /**
 * Implements a dictionary's functionality.
 */

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>


#include "dictionary.h"

/**
 * Returns true if word is in dictionary else false.
 */

 //create a trie data type
   typedef struct node
   {
        bool is_word;
        struct node *children[27]; //this is a pointer too!  
   }node; 

 //function prototype

 void un_node (node *node_name);
 void nullpoint (node *node_name);

 //initialize root
    node *root;       


bool check(const char *word)
{
    //create a trav pointer
    node *cursor = root;        
    int i = 0;

    while(word[i] != '\0')
    {
            char ch = word[i]; 
            int index = (tolower(ch) - 97);

            if(index == -58)
            {
                index = 26;
            }

           //validate index
           if(index < 0 || index > 26)
           {
               printf("Error: index\n");
               return false;
           }

        if(cursor -> children[index] != NULL)
            {
                cursor = cursor -> children[index];
                i++;
            }
        else
            {
                //if it is NULL then word is not in dictionary
                return false;
            }

    }
    //end of word, so check if there is a flag from load
    if(cursor -> is_word == true)
    {
        return true;
    }
    else
        return false;

}

/**
 * Loads dictionary into memory. Returns true if successful else false.
 */
bool load(const char *dictionary)
{
    //malloc space for root node
    root = malloc(sizeof(node));

    //all of root's children point to NULL now
    nullpoint (root);

   //open dictionary
   FILE *dptr = fopen(dictionary, "r");
   if(dptr == NULL)
   {
       return false;
   }


   char *c = malloc(sizeof(char));
   node *next_node;

   //scan the file char by char until end and store it in c
   while(fscanf(dptr,"%s",c) != EOF)
   {

       //in the beginning of every word, make a traversal pointer copy of root so we can always refer back to root
       node *trav = root;

       //when temp increments, it moves on to next character of word
       char *temp;
       temp = c;

       //repeat for every word
       while ((*temp) != '\0')
       {
            //convert char into array index
           int alpha = (tolower(*temp) - 97);

           //handle apostrophe
           if(alpha == -58)
           {
               alpha = 26;
           }

           //validate alpha
           if(alpha < 0 || alpha > 26)
           {
               printf("Error: alpha\n");
               return false;
           }


           //if array element is pointing to NULL, i.e. it hasn't been open yet,
            if(trav -> children[alpha] == NULL)
                {

                //then malloc next node and point it with the cursor. 
                next_node = malloc(sizeof(node));

                //initialize children of newly allocated node    
                nullpoint(next_node);

                //cursor points at the newly allocated memory
                trav -> children[alpha] = next_node; 
                //cusor moves on
                trav = trav -> children[alpha];//null?

                //quit if malloc returns null
                if(next_node == NULL)
                    {
                        printf("Could not open dictionary");
                        return false;
                    }

                }

            else
                {
                //if an already existing path, just go to it
                trav = trav -> children[alpha];
                } 

                //increment the address of temp variable
                temp++;
        }
        //a word is loaded. 
        trav -> is_word = true;

   }
   //success
   fclose(dptr);
   return true;
}

/**
 * Returns number of words in dictionary if loaded else 0 if not yet loaded.
 */
unsigned int size(void)
{
    // TODO
    return 0;
}

/**
 * Unloads dictionary from memory. Returns true if successful else false.
 */
bool unload(void)
{
    node *cursor = root;
    un_node(cursor);
    return true;
}

void un_node (node *cursor)
{
    for(int a = 0; a<27; a++)
    {
        //if the children's pointee is not NULL, i.e. this is not a dead end
        if(cursor -> children[a] != NULL)
        {
            //go back to the beginning (with cursor -> children[a] as new argument) restart this function
            un_node(cursor -> children[a]);
        }

    }
    //and when it is dead end, start to   
    free(cursor);
    return;
}

//function that points all children of node to NULL
void nullpoint (node *node_name)
{
    for(int t=0;t<27;t++)
    {
        node_name -> children[t] = NULL;
    }
}

0 个答案:

没有答案