Dicitonnaire en c

Fermé
luck22 Messages postés 11 Date d'inscription mardi 29 décembre 2009 Statut Membre Dernière intervention 2 janvier 2010 - 29 déc. 2009 à 02:48
loupius Messages postés 697 Date d'inscription dimanche 1 novembre 2009 Statut Membre Dernière intervention 31 décembre 2017 - 29 déc. 2009 à 17:11
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

7 réponses

Pacorabanix Messages postés 3248 Date d'inscription jeudi 23 août 2007 Statut Membre Dernière intervention 19 mai 2013 661
29 déc. 2009 à 04:32
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
luck22 Messages postés 11 Date d'inscription mardi 29 décembre 2009 Statut Membre Dernière intervention 2 janvier 2010
29 déc. 2009 à 11:52
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
loupius Messages postés 697 Date d'inscription dimanche 1 novembre 2009 Statut Membre Dernière intervention 31 décembre 2017 148 > luck22 Messages postés 11 Date d'inscription mardi 29 décembre 2009 Statut Membre Dernière intervention 2 janvier 2010
29 déc. 2009 à 12:31
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
luck22 Messages postés 11 Date d'inscription mardi 29 décembre 2009 Statut Membre Dernière intervention 2 janvier 2010 > loupius Messages postés 697 Date d'inscription dimanche 1 novembre 2009 Statut Membre Dernière intervention 31 décembre 2017
29 déc. 2009 à 12:53
donc il s'agit d'insérer un mot caractère par caractère
0
luck22 Messages postés 11 Date d'inscription mardi 29 décembre 2009 Statut Membre Dernière intervention 2 janvier 2010
29 déc. 2009 à 12:39
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
loupius Messages postés 697 Date d'inscription dimanche 1 novembre 2009 Statut Membre Dernière intervention 31 décembre 2017 148
29 déc. 2009 à 13:44
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
luck22 Messages postés 11 Date d'inscription mardi 29 décembre 2009 Statut Membre Dernière intervention 2 janvier 2010
29 déc. 2009 à 14:07
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

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
loupius Messages postés 697 Date d'inscription dimanche 1 novembre 2009 Statut Membre Dernière intervention 31 décembre 2017 148
29 déc. 2009 à 14:27
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
luck22 Messages postés 11 Date d'inscription mardi 29 décembre 2009 Statut Membre Dernière intervention 2 janvier 2010
29 déc. 2009 à 14:51
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
loupius Messages postés 697 Date d'inscription dimanche 1 novembre 2009 Statut Membre Dernière intervention 31 décembre 2017 148 > luck22 Messages postés 11 Date d'inscription mardi 29 décembre 2009 Statut Membre Dernière intervention 2 janvier 2010
29 déc. 2009 à 15:08
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
luck22 Messages postés 11 Date d'inscription mardi 29 décembre 2009 Statut Membre Dernière intervention 2 janvier 2010 > loupius Messages postés 697 Date d'inscription dimanche 1 novembre 2009 Statut Membre Dernière intervention 31 décembre 2017
29 déc. 2009 à 15:17
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
loupius Messages postés 697 Date d'inscription dimanche 1 novembre 2009 Statut Membre Dernière intervention 31 décembre 2017 148
29 déc. 2009 à 15:39
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
luck22 Messages postés 11 Date d'inscription mardi 29 décembre 2009 Statut Membre Dernière intervention 2 janvier 2010
29 déc. 2009 à 15:45
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
loupius Messages postés 697 Date d'inscription dimanche 1 novembre 2009 Statut Membre Dernière intervention 31 décembre 2017 148
29 déc. 2009 à 16:13
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
luck22 Messages postés 11 Date d'inscription mardi 29 décembre 2009 Statut Membre Dernière intervention 2 janvier 2010
29 déc. 2009 à 16:53
je vous remercie en touc as je vais refléchir à ça et revenir aprés pour vous montrez ce que j'ai eu
0
loupius Messages postés 697 Date d'inscription dimanche 1 novembre 2009 Statut Membre Dernière intervention 31 décembre 2017 148 > luck22 Messages postés 11 Date d'inscription mardi 29 décembre 2009 Statut Membre Dernière intervention 2 janvier 2010
29 déc. 2009 à 17:11
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