[C] [urgent] supprimer la derniere cellule d une file ?

supprimer la derniere cellule d une file ? [C] [urgent] - C - Programmation

Marsh Posté le 18-06-2006 à 15:21:51    

Salut a tous, je suis trop en galere pke mon projet bloque a cause d un probleme bizarre. Voyez plutot :
 
void construire_arbre_recouvrement(T_File_message file){
     
    T_File_message courant=file;
    while(courant->suivant){
        courant=courant->suivant;
    }    
    T_Routeur * pere=courant->pere;
    T_Routeur * routeur=courant->fils;
    T_Cle cle= courant->cle;
    printf("courant: %x\n",courant);
    printf("file: %x\n",file);    
    free(courant);
    courant=NULL;
    printf("apres liberation courant: %x\n",courant);
    printf("apres liberation file: %x\n",file);    
    assert(courant == NULL);  
 
 
 
 
c est la partie du code qui foire. Qd le programme passe pr la premiere fois dans cette fonction la file contient 1 message et devrait donc, par l intermediare du pointeur courant, se retrouver a NULL apres la libération (puisque dans ce cas courant = file). Bref, a l execution ca m affiche:
 
 
courant: 2ad48
file: 2ad48
apres liberation courant: 0
apres liberation file: 2ad48
 
 
Donc en fait le free ne marche pas du tout !!!!!!! Qq1 pourrait m aider ?


Message édité par XTinX le 18-06-2006 à 20:48:25
Reply

Marsh Posté le 18-06-2006 à 15:21:51   

Reply

Marsh Posté le 18-06-2006 à 15:41:26    

file pointe toujours sur l'adresse 2ad48 mais cette adresse ne contient plus rien vu que tu l'as libérée via le free de courant

Reply

Marsh Posté le 18-06-2006 à 16:22:17    

Je@nb a écrit :

file pointe toujours sur l'adresse 2ad48 mais cette adresse ne contient plus rien vu que tu l'as libérée via le free de courant


 
file vaut 2ad48, c'est la valeur du pointeur ! C est pour ca que je comprends pas.

Reply

Marsh Posté le 18-06-2006 à 16:43:14    

Code :
  1. T_File_message courant=file; //je suppose que courant est un pointeur et file aussi
  2. printf("courant: %x\n",courant); // j'affiche l'adresse pointée par courant
  3. printf("file: %x\n",file); // j'affiche l'adresse pointée par file
  4. free(courant); // je libère la structure qui est pointée par courant, donc je libère xx octets à l'adresse qui débute à *courant
  5. courant=NULL; // je fais pointer courant maintenant à NULL
  6. printf("apres liberation courant: %x\n",courant); // j'affiche l'adresse pointée par courant
  7. printf("apres liberation file: %x\n",file); // j'affiche l'adresse pointée par file


Vu que tu n'a pas modifiée file c'est normale que sa valeus (aka l'adresse qu'il pointe) soit la même adresse que avant.
Maintenant si tu fais un printf("file pointe sur : %x",*file); tu va te prendre un segfault vu que l'adresse pointée par file a été libérée

Reply

Marsh Posté le 18-06-2006 à 18:28:03    

Comment faut faire alors pour parcourir la file jusqu a la derniere cellule, l'utiliser et la liberer (et donc mettre le champ "suivant" de la cellule precedante à NULL) ????

Reply

Marsh Posté le 18-06-2006 à 18:43:13    

Help please, j en suis la :
 
 
void construire_arbre_recouvrement(T_File_message * file){
     
    T_File_message initiale=*file;  
    T_File_message * courant=file;
    while((*courant)->suivant){
 printf("while\n" );    
        *courant=(*courant)->suivant;
    }    
    T_Routeur * pere=(*courant)->pere;
    T_Routeur * routeur=(*courant)->fils;
    T_Cle cle= (*courant)->cle;
    free((*courant));
    (*courant)=NULL;
    assert(*courant == NULL);
    *file=initiale;
 
 
mais ca ne marche tjrs pas, comme il y a un appel recursif plus loins ds la fonction, je boucle dans le while


Message édité par XTinX le 18-06-2006 à 18:44:16
Reply

Marsh Posté le 18-06-2006 à 18:50:45    

XTinX a écrit :

Comment faut faire alors pour parcourir la file jusqu a la derniere cellule, l'utiliser et la liberer (et donc mettre le champ "suivant" de la cellule precedante à NULL) ????


Hum... ta question dénote un petit défaut de conception.
Il te faut distinguer "utilisation" et "libération" sinon cela risque de te mener à de gros pb.
 
Sinon, pour libérer le dernier élément, il sufit de balayer toute la file en mémorisant à chaque fois l'élément précédent

void freeLast(T_file *cellule)
{
      T_file *courant;
      T_file *prev;
 
       // Si la file est vide => Arrêt fonction (inutile si t'es certain que ça n'arrive jamais)
       if (courant == NULL)
           return;
       
      // Balayage de toute la file
      for (courant=cellule, prev=NULL; courant->suivant != NULL; courant=courant->suivant)
           prev=courant;
 
      // On libère le courant (qui se trouve sur le dernier élément)
      free(courant);
 
      // Si le précédent n'est pas nul (donc s'il y a au-moins deux éléments)
      if (prev)
      {
           // On positionne son suivant à NULL
           prev->suivant=NULL;
      }
}


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 18-06-2006 à 18:58:16    

Le probleme c est que je l utilise et une fois que c est fait je la libère !
 
je vais essayer avec ta fonction merci !

Reply

Marsh Posté le 18-06-2006 à 19:04:04    

Bon et bien ca ne marche tjrs pas.
 
Y a aussi un detail :
 
T_File_message est de type pointeur sur T_Message (qui est le type de chaque cellule)

Reply

Marsh Posté le 18-06-2006 à 19:06:10    

Voial le code en entier:
 
 
void construire_arbre_recouvrement(T_File_message * file){
     
    T_File_message  courant=*file;
    while(courant->suivant){
 printf("while\n" );    
        courant=courant->suivant;
    }  
    T_Routeur * pere=courant->pere;
    T_Routeur * routeur=courant->fils;
    T_Cle cle= courant->cle;
    freeLast(*file);
    printf("taille file : %d\n",taille_file(*file));  
    if(indice_cle_presente(*routeur,cle)== -1){    
 T_Table * table = creer_table_routage(pere,cle);
 table_add(&routeur->tables,table);
 if(pere){
     T_Table * table_paternelle;
     table_paternelle=table_routage(*pere,cle);
     routeur_add(&table_paternelle->fils,routeur);
 }
 for(int i=0;i<(routeur->voisins).nb;i++){
     ajouter_dans_file(file,routeur,routeur->voisins.elements[i],cle);
 }
    }
     
    if(*file){
 construire_arbre_recouvrement(file);
    }
}

Reply

Marsh Posté le 18-06-2006 à 19:06:10   

Reply

Marsh Posté le 18-06-2006 à 19:08:28    

et son petit frere :
 
 
 
 
void ajouter_dans_file(T_File_message *file,T_Routeur * pere,T_Routeur * fils,T_Cle cle){
 
    T_File_message ptr_message;
 
 
    ptr_message=malloc(sizeof(T_Message));
    ptr_message->pere=pere;
    ptr_message->fils=fils;
    ptr_message->cle=cle;
    ptr_message->suivant=*file;
    *file=ptr_message;
}

Reply

Marsh Posté le 18-06-2006 à 19:21:11    

Cette fonction ajoute un element en debut de file
 
C est peut etre celle la qui foire ??

Reply

Marsh Posté le 18-06-2006 à 19:35:20    

Ca marche tjrs pas  :cry:  :cry:  :cry:  :cry:  :cry:

Reply

Marsh Posté le 18-06-2006 à 20:40:33    

Reply

Marsh Posté le 18-06-2006 à 21:24:26    


Comment as-tu déclaré T_File_message? et T_routeur et T_cle
Parce que là tu es en train de jouer à placer des & et de * de façon complètement aléatoire. Cela dit c'est vrai qu'au pif tu as une chance non nulle pour que ça finisse par fonctionner.

Message cité 1 fois
Message édité par GrosBocdel le 18-06-2006 à 21:27:26
Reply

Marsh Posté le 18-06-2006 à 21:56:30    

XTinX a écrit :

void construire_arbre_recouvrement(T_File_message * file){
     
    T_File_message  courant=*file;
    while(courant->suivant){
 printf("while\n" );    
...
}



Horreur !!! Tu déclares un élément nommé "courant" de type "T_file_message" et tu lui passes en copie "*file" (la copie de structures, même si ça peut se faire avec précautions, c'est LONG !!!)
Mais dans la ligne du dessous, tu l'utilises avec l'opérateur "->" comme si c'était un pointeur !!!
Je crois que tu te mélanges sacrément les pinceaux avec les pointeurs, les structures, les pointeurs de structures et tout le reste...
 
Je vais essayer de te résumer le principe de manipulations des listes
1) tu déclares une structure te permettant de manipuler un élément de ta liste. Cette structure contient les données plus un pointeur contenant l'adresse de l'élément suivant. Du style

typedef struct s_noeud {
    data
    data
    data
    struct s_noeud *suivant;
} t_noeud;


 
2) tu déclares une structure te permettant de manipuler ta liste complète. En fait, cette structure contient l'adresse du premier élément de ta liste. Avec ce premier élément tu peux aller au suivant, puis au suivant etc.
La structure peut contenir d'autres objets utiles, comme un pointeur sur le dernier, un pointeur sur l'élement en cours de traitement, etc. C'est totalement facultatif mais aussi totalement évolutif et modulable. Style

typedef struct {
    t_noeud *premier;
    t_noeud *dernier;
    t_noeud *courant;
} t_liste;


Si un élément t'intéresse pas, tu le mets pas. Si t'as besoin d'autres éléments, tu les rajoutes.
 
Ensuite, dans ton "main()", tu déclares juste un "t_liste liste" et tu remplis chaque element à "NULL". Avec cette simple variable (qui peut être vue comme "poignée" de ta liste), tu tiens ta liste entière. Lorsque tu veux passer ta liste à une fonction quelconque, tu lui passes "&liste" et la fonction reçoit un pointeur sur "t_liste" style "t_liste *liste". Avec ce pointeur, ta fonction a accès au premier élément (avec "liste->premier" ) puis du premier elle peut passer au suivant etc etc et traiter toute la liste.
 
Dernier conseil: bien souvent, un dessin aide à la compréhension...
 

GrosBocdel a écrit :

Cela dit c'est vrai qu'au pif tu as une chance non nulle pour que ça finisse par fonctionner.


Cette hypothèse a déjà été évoquée. Si tu places un singe devant une machine à écrire durant un temps infini, tu obtiendras à un moment ou un autre l'ensemble complet des oeuvres de Shakespeare... :D  


Message édité par Sve@r le 18-06-2006 à 22:00:56

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 19-06-2006 à 00:03:28    

Soit tu le fais en itératif avec un pointeur qui pointe sur un élément de ta file et que tu déplace, soit tu y va en récursif.
 
genre :
 

Code :
  1. typedef struct telem {
  2.   int val;
  3.   struct telem *suivant;
  4. } elem;
  5. typedef file *elem;
  6. file mafile;
  7. //Remplissage de mafile
  8. file delLast(file uneliste) {
  9.   if (uneliste == NULL) { // Si la file est nulle
  10.      return NULL;
  11.   }
  12.   if (uneliste->suivant == NULL) {
  13.     free(uneliste);
  14.     return NULL;
  15.   }
  16.   uneliste->suivant = delLast(uneliste->suivant);
  17.   return uneliste;
  18. }

Reply

Marsh Posté le 19-06-2006 à 09:20:17    

En fait j ai trouvé la solution, il faut faire 2 cas:
 
le cas ou tu supprimes le premier éléments de la liste (si jamais il n y a que ca ds la liste)  
 
et le cas ou tu supprimes le dernier element.
 
 
 
La premiere fois tu utilises un pointeur de pointeur vers la premiere cellule (pour pouvoir modifier le pointeur)
 
La deuxieme fois tu utilises un pointeur simple pour parcourir la file
 
 
 
Voila ! et merci qd meme a tous

Reply

Marsh Posté le 20-06-2006 à 23:49:01    

Je@nb a écrit :

Soit tu le fais en itératif avec un pointeur qui pointe sur un élément de ta file et que tu déplace, soit tu y va en récursif.


Le récursif est à éviter chaque fois que c'est possible !!!


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed