2017-08-19 4 views
0

J'essaie de mettre en œuvre une structure de données trie pour vérifier l'orthographe d'un fichier texte donné. Actuellement, il semble fonctionner pour quelques mots dans le fichier, puis il atteint un défaut de seg. J'ai essayé de déboguer pour trouver le coupable, mais tout ce que j'ai trouvé, c'est que la valeur de "lettre" conserve des valeurs négatives apparemment aléatoires (elle devrait être comprise entre 1 et 27, inclusivement). Normalement, le problème de la faute seg apparaît presque instantanément après le démarrage du programme, donc je ne sais pas pourquoi le problème surgit au milieu du programme.Erreur de segmentation dans l'implémentation de Trie dans C

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

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

    #include "dictionary.h" 


    //create global root node 
    Trienode *root; 
    //create word counter for size() function 
    unsigned int wordcount = 0; 

    //creates an empty node 
    Trienode * newnode() 
    { 
     Trienode *nnode = NULL; 
     nnode = (Trienode *)malloc(sizeof(Trienode)); 
     //initialize new node with null pointers and values 
     nnode -> parent = NULL; 
     for(int i = 0; i < 27; i++) 
     { 
      nnode -> children[i] = NULL; 
     } 
     return nnode; 
    } 

    void cleartrie(Trienode *head) 
    { 
     //if child node exists, free it, else continue with next iteration in for loop 
     if(head) 
     { 
      for(int i = 0; i < 27; i++) 
      { 
       cleartrie(head -> children[i]); 
      } 
      free(head); 
      head = NULL; 
     } 
    } 

    /** 
    * Returns true if word is in dictionary else false. 
    */ 
    bool check(const char *word) 
    { 
     int i = 0; 
     int letter; 
     Trienode *head = root; 

     while(word[i] != '\0') 
     { 
      if(isalpha(word[i])) 
      { 
       letter = word[i] - 'a'; 
      } 
      else //it must be an apostrophe 
      { 
       letter = word[i] - 13; 
      } 
      if(!(head -> children[letter])) 
      { 
       return false; 
      } 
      else //a pointer must exist 
      { 
       head = head -> children[letter]; 
      } 
      i++; 
     } 
     return true; 
    } 

    /** 
    * Loads dictionary into memory. Returns true if successful else false. 
    */ 
    bool load(const char *dictionary) 
    { 
     //open file 
     FILE *infile = fopen(dictionary, "r"); 
     Trienode *parnode; //parent node 
     root = newnode(); 
     Trienode *curnode = root; //current node 

     int letter = 0; 
     //while not end of file, read words 
     while(fgetc(infile) != EOF) 
     { 
      //while not end of word, read letters 
      for(;;) 
      { 
       int c; 
       //read current letter in file 
       c = fgetc(infile); 
       //convert input char to corresponding array location (a - z = 0-25, apostrophe = 26) 
       if(isalpha(c)) 
       { 
        letter = c - 'a'; 
       } 
       else if (c == '\'') 
       { 
        letter = c - 13; 
       } 
       //if end of string, exit loop 
       else if (c == '\0') 
       { 
        //end of word, so endofstring = true 
        wordcount++; 
        break; 
       } 
       //move to next letter if not either apostrophe or alphabetical 
       else 
       { 
        break; 
       } 
       //if pointer to letter of word doesn't exist, create new node 
       if(curnode -> children[letter] == NULL) 
       { 
        curnode -> children[letter] = newnode(); 
       } 
       //child node is the new current node 
       parnode = curnode; 
       curnode = curnode -> children[letter]; 
       curnode -> parent = parnode; 

      } 
      //return to root node 
      curnode = root; 
     } 

     fclose(infile); 
     return true; 
    } 


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

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

Désolé pour le mur du texte, mais pour la plus grande partie est juste là pour contexte (je espère). L'erreur de seg se produit sur la ligne if (! (Head -> children [letter])) de la fonction d'aide de vérification.

Merci d'avance!

+0

Je ne vois pas ce qu'est un Trienode dans votre code. Est-ce une structure? – Jerinaw

+1

Avez-vous utilisé un débogueur? À quels points de votre code exactement l'erreur set se produit (le débogueur devrait vous le dire)? Où voyez-vous que la valeur de 'letter' va de travers? Comme il s'agit d'une liste partielle de codes (et je ne suggérerais pas de mettre tout votre code sans réduire le problème), il est difficile de dire où le problème est juste de le "regarder". Faites plus de débogage et affinez-le. – lurker

+0

Utilisez valgrind. Il vous dira où sont vos problèmes. –

Répondre

1

Je suppose que votre fichier de test peut contenir des majuscules. Si c'est le cas, alors en soustrayant 'a' dans une tentative de remapper vos lettres se traduira par un nombre négatif, depuis 'A' < 'a'. Jetez un oeil à la ASCII Table. La conversion des lettres en minuscules en premier devrait résoudre votre problème.