Dicitonnaire en c

Bonjour tout le monde,
je veux coder un dicitonnaire en c en utilisant un arbre lexicographique alors j'ai défini ma strucutre comme suit :

typedef struct NOEUD
{
char lettre;
struct NOEUD *frere, *fils;
} Noeud, * Dictionnaire;

et pour ma fonction qui insére un caractere dans le dicitonnaire elle débute comme ça :

Noeud * inserer_caractere(Noeud * position , char c)

{Noeud * temp = position
Noeud * nouvelElement;
if (c < temp->lettre)
{nouvelElement = (Noeud*)malloc(sizeof(Noeud));
nouvelElement->lettre = c;
nouvelElement->frere = temp;
nouvelElement->fils = NULL;
return nouvelElement;
} etc

à l'éxécution j'ai une erreur de segmentation , et lorsque je debuggue avec (gdb)
il m'indique que c'est du à la ligne( if (c < temp->lettre) )
et je comprends pas pourquoi cette ligne provoque une erreur.
Je vous remercie
Configuration: Windows Vista
Firefox 3.5.6

7 réponses

  • Votes
  • Date
  • Date décroissante
  1. une erreur de segmentation, c'est une erreur mémoire. Ceci signifie qu'il doit y avoir un souci avec le pointeur que tu utilises (temp). Le pointeur ne pointe pas vers une zone valide. L'erreur se déclenche à cet endroit, car c'est là que ton pointeur mal initialisé est utilisé. Mais la véritable erreur logique est ailleurs.

    Quel est le pointeur qui pose problème ? réponse : temp
    D'où vient temp ? réponse : il vient de là : Noeud * temp = position
    d'où vient position ? c'est un paramètre de ta fonction. Il faut donc chercher là où tu appelles ta fonction. Le pointeur que tu lui donnes en paramètre est probablement mauvais.
    1. Merci pour vote réponse , mas fonction elle insére un seule caractére dans dans le dicitonnaire elle est appelée par une fonction qui insére un mot donc en paramétre je lui passe bien un char
    2. @luck22Je confirme la réponse de Paco: le paramètre 'position' ne doit pas être valide, est-ce un pointeur et si oui de l'espace mémoire lui a-t-il été alloué ?
      Tu peux donner l'autre fonction, sans oublier d'utiliser les balises 'code' sises à droite de la balise 'souligné'.
    3. @loupiusdonc il s'agit d'insérer un mot caractère par caractère
  2. oui tout à fait le paramétre "position" est un pointeur sur la tete de la liste et voici la fontion inser_mot qui fait appel à inserer_caractere
     Noeud * inserer_mot(Noeud * d , char * chaine)
       {
        // Noeud *  temp;
    	 //Noeud *  premier;
    	 Noeud *  pere=d,* temp , *premier;
    	 int      n,j,t;
    	 j=0;
    	 
    	 temp=inserer_caractere(d , chaine[0]);
    	 
    	 if((temp->lettre) < (d->lettre)) // dans ce cas on a une nvlle teste de liste
    	    d=temp;
    		pere=temp;
    		
    	 j++;
    		
    	
    		while ((pere->fils != NULL) && (j<strlen(chaine)))
    		{ premier = pere->fils;
    		  temp = inserer_caractere( premier , chaine[j]);
    		  if (temp->lettre < premier->lettre)
    		     pere->fils =temp;
    			 
    			 pere=temp;
    			 j++;
    	     }
    		 t=j;
    		 
    	for(j=t ; j<strlen(chaine); j++)
    	
    	     {pere->fils = nouvelleCellule(chaine[j]);
    		   pere= pere->fils;
    		 }
    		pere->fils = nouvelleCellule('#');
    		  return d;
    		 }
    1. Ce qui me semble curieux:
      temp = inserer_caractere(d, chaine[0]);
      if ((temp->lettre) < (d->lettre)) // dans ce cas on a une nvlle teste de liste

      Ce que nous savons c'est ce que retourne 'inserer_caractere' lorsque c'est une nouvelle tête de liste, ce que nous ne savons pas c'est ce que nous retourne 'inserer_caractere' dans l'autre cas. En effet, dans ce cas, qu'est-ce qui nous dit que le test est faux ?
      Ton code est difficile à suivre; pourquoi mettre 'j=0' et 'j++', il vaut mieux mettre 'j=1', pourquoi mettre 'pere=d', c'est inutile.
      Le plus sûr moyen de trouver ton erreur est de suivre les adresses de tes pointeurs, en espérant que ça plante assez vite ;-)
      Bonne réflexion.
      1. salut
        pour temp = inserer_caractere(d, chaine[0]);
        if ((temp->lettre) < (d->lettre))
        la en fait on regarder le racine du mot existe deja dans le dictionnaire si oui on change la tete de la liste c'est pour cela QU'ON INCRÉMENTE J CELA SIGNIFIE QU4IL Y A DEJA DES MOTS KI ONT la meme racine donc inutile de réinsérer le debut du mot qui existe deja
        1. Le code suivant:
            Noeud * pere=d,* temp , *premier;
            j=0;
            temp=inserer_caractere(d , chaine[0]);
            if((temp->lettre)<(d->lettre)) // dans ce cas on a une nvlle teste de liste
              d=temp;
            pere=temp;
            j++;
          est identique à ce code:
            Noeud *pere, *temp, *premier;
            temp = inserer_caractere(d, chaine[0]);
            if((temp->lettre) < (d->lettre)) // dans ce cas on a une nvlle tête de liste
              d = temp;
            pere = temp;
            j = 1;
          Mais ceci n'est gênant que pour la compréhension. Ce que j'aurais préféré savoir c'était ce que retourne la fonction 'inserer_caractere' quand ce n'est pas une nouvelle tête de liste.
          1. oui oui ces deux codes sont identiques et pour la fonction "insére_caractere" en fait le pointeur premier pointe toujours sur une tete de liste dans le premier appel de la fonction "insere_caractere"

            Noeud *pere, *temp, *premier;
              temp = inserer_caractere(d, chaine[0]);

            la je verifie si la racine du mot existe deja si oui je change ma tete de liste et j'insere les caracteres à partir de cette nouvelle tete de liste
            la fonction "insere caractère"soit elle insere un caractere en tete de la liste soit au milieu ou soit enfin d eliste si le caractere n'existait ps au paravant dans le dictionnaire
          2. @luck22Oui, j'avais à peu près compris ;-) mais comme tu n'as pas donné complètement la fonction 'insere_caractere', j'aurais aimé savoir ce qu'elle retourne quand ce n'est pas une nouvelle tête de liste, il doit bien y avoir un autre 'return'.
          3. @loupiusOUI elle retourne autre chose en fait c'est selon la position ou elle va placer le caractere

            Noeud * inserer_caractere(Noeud * position , char c)
            
            {Noeud * temp = position
            Noeud * nouvelElement;
            if (c < temp->lettre)
            {nouvelElement = (Noeud*)malloc(sizeof(Noeud));
            nouvelElement->lettre = c;
            nouvelElement->frere = temp;
            nouvelElement->fils = NULL;
            return nouvelElement;
            
            
               
               // si la lettre n'est pas placée au début , soit on va la palcer enfin de liste soit quelque part entre le début et la fin de la liste,
               // on se déplace alors dans la liste grace au pointeur temp pour savoir la bonne position ou ns devons insérer notre lettre
               
               while((temp->frere !=NULL) && ((temp->frere->lettre )<= c))
               temp=temp->frere;
               
               if (c<(temp->frere->lettre))
               {
                nouvelElement = (Noeud*)malloc(sizeof(Noeud));
            	nouvelElement->lettre = c;
                nouvelElement->frere = temp->frere;
                nouvelElement->fils = NULL;
            	temp->frere=nouvelElement;
            	
            	return nouvelElement;
            	}
            	
            	
               if ((temp->frere)==NULL)
               
               {nouvelElement = (Noeud*)malloc(sizeof(Noeud));
                nouvelElement->lettre = c;
                nouvelElement->frere = NULL;
                nouvelElement->fils = NULL;
            	temp->frere=nouvelElement;
            	
            	return nouvelElement;
            	}
            	
            	if (c == temp->lettre)
            	     return temp;

            voila c 'est le code de la fonction
        2. Si j'ai bien compris, après remise en forme, on obtient:
          Noeud* inserer_caractere(Noeud* position ,char c)
          {
            Noeud* temp = position
            Noeud* nouvelElement;
          
            if (c < temp->lettre)
            {
              nouvelElement = (Noeud*)malloc(sizeof(Noeud));
              nouvelElement->lettre = c;
              nouvelElement->frere = temp;
              nouvelElement->fils = NULL;
              return nouvelElement;
            }
            if ((temp->frere)==NULL)
            {
              nouvelElement = (Noeud*)malloc(sizeof(Noeud));
              nouvelElement->lettre = c;
              nouvelElement->frere = NULL;
              nouvelElement->fils = NULL;
              temp->frere=nouvelElement;
              return nouvelElement;
            }
            if (c == temp->lettre)
              return temp;
          }
          Alors là il y a un problème... il y a des cas où la fonction ne retourne rien... ou plutôt n'importe quoi. Ce n'est peut-être pas la solution à ton problème mais une erreur de ce type entraîne à un moment ou à un autre un 'segment fault'.
          1. je pense que t'as oublié ce cas ci :
            while((temp->frere !=NULL) && ((temp->frere->lettre )<= c))
               temp=temp->frere;
               
               if (c<(temp->frere->lettre))
               {
                nouvelElement = (Noeud*)malloc(sizeof(Noeud));
            	nouvelElement->lettre = c;
                nouvelElement->frere = temp->frere;
                nouvelElement->fils = NULL;
            	temp->frere=nouvelElement;
            	
            	return nouvelElement;
            	}

            sinon tous les cas sont traités je pense
        3. Ok, j'en avais oublié un bout, donc la fonction est bien:
          Noeud* inserer_caractere(Noeud* position ,char c)
          {
            Noeud* temp = position
            Noeud* nouvelElement;
          
            if (c < temp->lettre)
            {
              nouvelElement = (Noeud*)malloc(sizeof(Noeud));
              nouvelElement->lettre = c;
              nouvelElement->frere = temp;
              nouvelElement->fils = NULL;
              return nouvelElement;
            }
            while((temp->frere != NULL) && (temp->frere->lettre <= c))
              temp=temp->frere;
            if (c<(temp->frere->lettre))
            {
              nouvelElement = (Noeud*)malloc(sizeof(Noeud));
              nouvelElement->lettre = c;
              nouvelElement->frere = temp->frere;
              nouvelElement->fils = NULL;
              temp->frere=nouvelElement;
              return nouvelElement;
            }
            if ((temp->frere)==NULL)
            {
              nouvelElement = (Noeud*)malloc(sizeof(Noeud));
              nouvelElement->lettre = c;
              nouvelElement->frere = NULL;
              nouvelElement->fils = NULL;
              temp->frere=nouvelElement;
              return nouvelElement;
            }
            // 'Point X'
            if (c == temp->lettre)
              return temp;
          }
          Il y a donc bien des cas où la fonction ne retourne rien. Quand on arrive au 'Point X' et que 'c' est différent de 'temp->lettre' (ce qui doit bien arriver, sinon pourquoi faire un test? ), d'après toi: que se passe-t-il ?
          Bonne réflexion.
          1. je vous remercie en touc as je vais refléchir à ça et revenir aprés pour vous montrez ce que j'ai eu
          2. @luck22Il suffit ainsi de modifier la fin de la fonction:
              ...
              if (c == temp->lettre)
                return temp;
              printf ("Passe\n");
            }
            pour savoir si on passe par là; mais quand bien même on n'y passerait jamais il n'est pas correct de ne rien retourner, d'ailleurs le compilateur doit manifester en plaçant un 'warning'.
            Bonne continuation.