Dicitonnaire en c

luck22 Messages postés 13 Statut Membre -  
loupius Messages postés 789 Statut Membre -
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

  1. Pacorabanix Messages postés 4122 Date d'inscription   Statut Membre Dernière intervention   663
     
    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.
    0
    1. luck22 Messages postés 13 Statut Membre
       
      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
      0
      1. loupius Messages postés 789 Statut Membre 148 > luck22 Messages postés 13 Statut Membre
         
        Je 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é'.
        0
      2. luck22 Messages postés 13 Statut Membre > loupius Messages postés 789 Statut Membre
         
        donc il s'agit d'insérer un mot caractère par caractère
        0
  2. luck22 Messages postés 13 Statut Membre
     
    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;
    		 }
    0
  3. loupius Messages postés 789 Statut Membre 148
     
    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.
    0
  4. luck22 Messages postés 13 Statut Membre
     
    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
    0
  5. Vous n’avez pas trouvé la réponse que vous recherchez ?

    Posez votre question
  6. loupius Messages postés 789 Statut Membre 148
     
    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.
    0
    1. luck22 Messages postés 13 Statut Membre
       
      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
      0
      1. loupius Messages postés 789 Statut Membre 148 > luck22 Messages postés 13 Statut Membre
         
        Oui, 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'.
        0
      2. luck22 Messages postés 13 Statut Membre > loupius Messages postés 789 Statut Membre
         
        OUI 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
        0
  7. loupius Messages postés 789 Statut Membre 148
     
    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'.
    0
    1. luck22 Messages postés 13 Statut Membre
       
      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
      0
  8. loupius Messages postés 789 Statut Membre 148
     
    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.
    0
    1. luck22 Messages postés 13 Statut Membre
       
      je vous remercie en touc as je vais refléchir à ça et revenir aprés pour vous montrez ce que j'ai eu
      0
      1. loupius Messages postés 789 Statut Membre 148 > luck22 Messages postés 13 Statut Membre
         
        Il 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.
        0