[C] Listes chainées

Listes chainées [C] - Programmation

Marsh Posté le 13-02-2001 à 13:33:18    

D'abord voici mon typedef  
 
typedef struct art
 {
        struct art *suivant;
        char *nom;
        char *ref;
        double prix;
        int reste;
        }article;
 
et la partie de mon code qui est tres laide :
 
article* cherche_place(article *t, article* o)  //t est la tete de ma liste et o un article à insérer dans ma liste et je retourne un pointeur sur un article, soit une adresse.
   {
   article *lire=t;
 
   while(lire!=NULL)
    {
      if(strcmp((*lire).nom,(*o).nom)>0)
       {
        return lire;
        }
        lire=(*lire).suivant;      
    }
   getch();
   }
 
Ce que je veux, c'est me positionner n'importe ou ds ma liste chainée. Des que je trouve ((*lire).nom,(*o).nom)>0, je veux sortir de mon if ET de mon while. Ainsi, je retourne l'adresse de lire et donc la position ds ma liste, non ?
 
Le pb, c qd des que je rentre dans mon if, je recontre return, ce qui fait sortir de mon if et rerentrer dans mon while non ?
 
Bon, soyez indulgent, je debute. Le but est d'insérer des élements dans un tableau directement à la bonne place ( ordre alphabétique ). Je ne veux pas tout mettre à la queue et ensuite classer.
 
Merci d'avance !

Reply

Marsh Posté le 13-02-2001 à 13:33:18   

Reply

Marsh Posté le 13-02-2001 à 13:39:02    

le return te fait sortir de la fonction cherche_place()
 
ensuite on n'écrit pas (*lire).nom mais lire->nom
donc à changer à tous les endroits où tu cherches à accéder
à un élément d'une structure pointée.
 
fais les modifs et reteste
 
getch(), c'est quoi???
 

 


--Message édité par jupiler--

Reply

Marsh Posté le 13-02-2001 à 13:40:57    

ah oui, je suis avec borland, getch() <=> getchar() il me semble nop ?

Reply

Marsh Posté le 13-02-2001 à 13:43:35    

Ca ne change pas, mais je pense que c'est plutot du coté de l'algo que ca va pas non ?

Reply

Marsh Posté le 13-02-2001 à 13:51:35    

l'algo me semble bon, sauf que je ne vois pas à quoi sert le getch() et qu'il faut que tu ajoutes "return null" à la fin de la fonction

Reply

Marsh Posté le 13-02-2001 à 14:06:17    

Le return sort de la fct, meme un break sortirait de la boucle me semble-t-il... mais effectivment c'est laid...
Utilise des variables temporaires (en C++ des bool, en C des char ou des short)
 
result = NULL;  
do
{
 exitCondition = strcmp(lire->nom,o->nom);
 if(exitCondition)
  result = lire;
 lire = lire->suivant;
}
while(lire!=NULL && !exitcondition)
 
 return result;

Reply

Marsh Posté le 13-02-2001 à 14:11:04    

ok merci. Je vais voir ca.
 
J'ai une autre erreur, cette fois d'allocation de mémoire :
 
void preinsert(article *t, article *o)
   {
   article* sauve=o;
   o->suivant=t;
   t->suivant=sauve; // c'est la que ca merde
   }
 
Une ( autre ) idée ? :)

Reply

Marsh Posté le 13-02-2001 à 14:26:47    

euh, c'est sensé faire quoi?

Reply

Marsh Posté le 13-02-2001 à 14:36:47    

mdr, hum. Euh normalement ca serait d'insérer mon article dans ma lite juste apres t ( qui n'est pas la tete mais est l'adresse retourne par cherche place ).
 
Pour insérer mon article ds la liste entre 2 articles A et B pour avoir ca : A | mon_article | B ( A = t, mon_article= o B = A->suivant )
 
je dois sauver A->suivant
               Faire en sorte que A->suivant pointe vers mon_article  
               Et faire en sorte que mon_article pointe vers B soit A->suivant.

 

--Message édité par Evadream -jbd---

Reply

Marsh Posté le 13-02-2001 à 14:43:42    

deja ton getch() sert a koi ici ?? c bof de le mettre ici meme si c pour un debuggage :)
 
essaie une boucle du genre:
 
 
lire=t;
if ( o != null )
  while ( ( lire != null ) && ( strcmp((*lire).nom,(*o).nom)<=0 ) )
   lire = (*lire).suivant;
 
return lire;


---------------
"C'est le boulot qu'on ne commence jamais qui est le plus long à terminer"
Reply

Marsh Posté le 13-02-2001 à 14:43:42   

Reply

Marsh Posté le 13-02-2001 à 14:50:18    

jai pas essaye alors si ca marche tant mieux :D
 
Au fait, si tu veux inserer un elt dans ta liste... tu peux faire:
 
(*o).suivant = (*liste).suivant;
(*liste).suivant = o;
 
Mais, fait aussi un test avant sur la validité de tes variables !!!!
du style:  
 
if ( ( temp == null ) || (liste == null ) )
  return;
 
:D
J'espere que c bon ce ke je te dis paske je peux pas le tester ici alors... :D:D


---------------
"C'est le boulot qu'on ne commence jamais qui est le plus long à terminer"
Reply

Marsh Posté le 13-02-2001 à 15:02:27    

Evadream -jbd- a écrit a écrit :

ok merci. Je vais voir ca.
 
J'ai une autre erreur, cette fois d'allocation de mémoire :
 
void preinsert(article *t, article *o)
   {
   article* sauve=o;
   o->suivant=t;
   t->suivant=sauve; // c'est la que ca merde
   }
 
Une ( autre ) idée ? :)




 
Faut pas mettre o->suivant = t-> suivant ?

Reply

Marsh Posté le 13-02-2001 à 15:04:04    

C'est ce que je me suis dit en postant, mais ca marche tjs pas ;)
 
je vais réfléchir à toutes vos indications

Reply

Marsh Posté le 13-02-2001 à 15:08:59    

T'es sûr que la structure pointée par t est allouée ????


---------------
"If you can walk away from a landing, it's a good landing. If you use the airplane the next day, it's an outstanding landing." - Chuck Yeager. | Chaîne YT | Photos
Reply

Marsh Posté le 13-02-2001 à 15:14:22    

Verdoux> Sisi, je pense aussi :) (cf. mon post precedent)
 
A mon avis, t'as du oublier un chtit malloc qqpart :D


---------------
"C'est le boulot qu'on ne commence jamais qui est le plus long à terminer"
Reply

Marsh Posté le 13-02-2001 à 15:14:56    

excellente remarque!
 
sinon, suffit de mettre:
 
o->suivant=t->suivant (o recupère B comme suivant)
t->suivant = o (t recupère o comme suivant)
 
mais il est primordiale que t et o aient été alloués

Reply

Marsh Posté le 13-02-2001 à 15:15:40    

p.s: D'où le petit test que je te disais plus haut :D


---------------
"C'est le boulot qu'on ne commence jamais qui est le plus long à terminer"
Reply

Marsh Posté le 13-02-2001 à 15:17:10    

lorsque mes articles sont crées je fait ca :
 
objet=(article*)malloc(sizeof(article));
 
Mais je pense avoir un tit prob, vu que ds mon main j'ai un tete=NULL; qui traine, je vais voir ca.
 
Merci encore !

Reply

Marsh Posté le 13-02-2001 à 15:44:10    

"ds mon main j'ai un tete=NULL" :D:D:D


---------------
"If you can walk away from a landing, it's a good landing. If you use the airplane the next day, it's an outstanding landing." - Chuck Yeager. | Chaîne YT | Photos
Reply

Marsh Posté le 13-02-2001 à 15:45:42    

rhooo :)

Reply

Marsh Posté le 13-02-2001 à 15:54:04    

bouuuuhhhh :lol:


---------------
"C'est le boulot qu'on ne commence jamais qui est le plus long à terminer"
Reply

Marsh Posté le 13-02-2001 à 16:02:12    

sous borland c++ sous windowd si tu mets un getch()en fin de prog
parfois pour faire une sorte de pause  
-> getch() = attente d'une saisie de char au clavier
 
si pas de getch alors la fenetre dos se ferme et on voit rien


---------------
-Hassan Cehef --> C'est possible -Roberttripoux --> Les bons comptes font les bons amis
Reply

Marsh Posté le 13-02-2001 à 16:06:09    

BENB, je ne comprends pas le : if(exitCondition)
 
exitCondition est <0 == 0 ou >0, mais qd rentre t'on ds le if ?

Reply

Marsh Posté le 13-02-2001 à 16:07:20    

c bien ce ke je pensais... Mais moi je prefere des println() ou printf() (jsais plus c koi le bon en C :D )
 
Car pour le debuguage, rien de tel !!!!
les getch() & Co. c'est bof car si tas une erreur avant.. ben tu vois rien. et tu sais pas ou c en +.
Pi si tu veux voir le resultat simplement, ben le printxx() le fait plutot bien. :)


---------------
"C'est le boulot qu'on ne commence jamais qui est le plus long à terminer"
Reply

Marsh Posté le 13-02-2001 à 16:08:53    

de quel if tu parles ?? :??:


---------------
"C'est le boulot qu'on ne commence jamais qui est le plus long à terminer"
Reply

Marsh Posté le 13-02-2001 à 16:10:39    

cf post de BENB :
 
result = NULL;  
do  
{  
exitCondition = strcmp(lire->nom,o->nom);  
if(exitCondition)  
  result = lire;  
lire = lire->suivant;  
}  
while(lire!=NULL && !exitcondition)  
 
return result;

Reply

Marsh Posté le 13-02-2001 à 16:23:06    

ben ... je crois que le if en C cest TRUE si different de zero
alors sa condition marche pas tout a fait... car si cest negatif sa sort quand meme !!! :D
 
Bref, essaie mon truc (cf. mon post plus haut) ca devrais marcher... en fin je crois :D:D


---------------
"C'est le boulot qu'on ne commence jamais qui est le plus long à terminer"
Reply

Marsh Posté le 13-02-2001 à 16:33:41    

C'est pas une hypothèse, c'est sûr.
 
tu peux même définir
#define NOK 0
#define OK  !NOK
 
si tu veux.


---------------
"If you can walk away from a landing, it's a good landing. If you use the airplane the next day, it's an outstanding landing." - Chuck Yeager. | Chaîne YT | Photos
Reply

Marsh Posté le 13-02-2001 à 16:45:04    

Je suis repartit de zéro pour y voir plus clair.
 
#include<stdio.h>
#include<conio.h>
#include<alloc.h>
#include<string.h>
 
typedef struct art
   {
   struct art *suivant;
   char *nom;
   char *ref;
   double prix;
   int reste;
   }article;
 
 
 
article* creer();
article* detection(article* t, article* o);
void inserer(article* t,article* o);
void preinsert(article* t, article* o);
 
 
 
void main()
   {
   article* tete;
   article* objet;
   char rep='o';
   //creation de la liste
   tete=NULL;
 
   printf("Creation d'une liste chainee\n" );
   getch();
 
   while(rep=='o')
      {
      objet=creer();
      clrscr();
      printf("Donner son nom : " );
      scanf(" %s", objet->nom);
      inserer(tete,objet);
      printf("\ncontinuer ? :" );
      scanf(" %c", &rep);
      }
   getch();
   }
 
 
 
article* creer()
   {
   article* objet;
   objet=(article*)malloc(sizeof(article));
   objet->nom=(char*)malloc(sizeof(char));
   objet->ref=(char*)malloc(sizeof(char));
   objet->suivant=NULL;
   return objet;
   }
 
 
void inserer(article* t, article *o)
   {
   article* cursor=detection(t,o);
   preinsert(cursor,o);
   }
 
void preinsert(article *t, article *o)
   {
   o->suivant=t->suivant; // c'est la qu'il y a erreur
   t->suivant = o;  
   }
 
article* detection(article* t, article* o)
   {
   article* lire=t;
   
   if ( o != NULL )
      {
      while ( ( lire != NULL ) && ( strcmp((*lire).nom,(*o).nom)<=0 ) )
       {
        lire = lire->suivant;
        }
      }
      return lire;
   }
 
je ne comprends pas pkoi lorsque j'execute, j'ai ce probleme, pourtant t et o sont allouees non ?
 
Desole de vous prendre le choux

 

--Message édité par Evadream -jbd---

Reply

Marsh Posté le 13-02-2001 à 16:55:14    

Arf et si t est à NULL comme au début quand ta liste est vide :D
t->suivant=qqchose ça fait du dégât :D
 
Il faut que tu réécrives les cas spécifiques d'insertion dans une liste vide ou d'une insertion en tête.

 

--Message édité par Toxin--


---------------
"If you can walk away from a landing, it's a good landing. If you use the airplane the next day, it's an outstanding landing." - Chuck Yeager. | Chaîne YT | Photos
Reply

Marsh Posté le 13-02-2001 à 17:09:20    

chuis con.

Reply

Marsh Posté le 13-02-2001 à 17:10:20    

teste dans preinsert si t est null
 
if (t != NULL)
{
o->suivant=t->suivant;
   t->suivant = o;  
}
else
o->suivant = NULL;

Reply

Marsh Posté le 13-02-2001 à 17:12:10    

Evadream -jbd- a écrit a écrit :

chuis con.




 
Nan t'es un newbie, tout le monde a fait cette connerie je te rassure.


---------------
"If you can walk away from a landing, it's a good landing. If you use the airplane the next day, it's an outstanding landing." - Chuck Yeager. | Chaîne YT | Photos
Reply

Marsh Posté le 13-02-2001 à 17:13:12    

;)

Reply

Marsh Posté le 13-02-2001 à 17:14:30    

ouaips... pi si tu m'avais écouter en mettant le chtit test de validités de tes variables avant l'insertion, t'aurais pas le pb de Null Pointer Exception !!!
 
Tu peux mettre la contition dans ta fonction inserer()
juste apres la fonction detection().
Du style:  
 
  if ( cursor == null ) // C la tete de la liste
  {
     t = o;
  }
  else
  {
     preinsert(...);
  }
 
Mais faut que tu passes ton article "t" en pointeur de pointeur
(Expression barbare :D )
Sinon, t'auras pas ta liste tout comme i fo :D
Du style :  void inserer(article **t, article *o) { ... }
 
Voilà, pi jespere ke c bon :)


---------------
"C'est le boulot qu'on ne commence jamais qui est le plus long à terminer"
Reply

Marsh Posté le 14-02-2001 à 10:27:50    

Vi mais si t est un article **, c'est *t = o qu'il faut faire.
 
Vu comment tu as développé ton code, il vaut mieux créer une fonction spécifique void inserertete(article **t, article *o) ;
 
L'appel de la fonction quant à lui est inserertete(&t, o) ;

 

--Message édité par Toxin--


---------------
"If you can walk away from a landing, it's a good landing. If you use the airplane the next day, it's an outstanding landing." - Chuck Yeager. | Chaîne YT | Photos
Reply

Marsh Posté le 14-02-2001 à 11:53:29    

Bon, j'ai repris en corrigeant a vue d'oeuil le code de ton exemple.
Ce devrait avoir cette aspect la pour tourner:
 
#include<stdio.h>  
#include<conio.h>  
#include<alloc.h>  
#include<string.h>  
 
typedef struct art  
   {  
   struct art *suivant;  
   char *nom;  
   char *ref;  
   double prix;  
   int reste;  
   }article;  
 
 
 
article* creer();  
article* detection(article* t, char* nom);  
void inserer(article* t,article* o);  
void preinsert(article* t, article* o);  
 
 
 
int main()  
   {  
   article* tete = NULL;  
   article* objet;  
   char rep;     /* assigne sur ton premier getch */
   char buffer[255];  /* on peut supposer que l'utilisateur taperas des noms moins long */
 
   printf("Creation d'une liste chainee\n" );  
   getch();  
 
   while(rep=='o' )  
      {  
      objet=creer();
      clrscr();  
      printf("Donner son nom : " );  
      /* scanf(" %s", objet->nom); la ca peche: tu n'avais alloue qu'un caractere */
      scanf(" %s", buffer);
      objet->nom = strdup(buffer);
 
      if (!tete)
 tete = objet; /* tu assignes tete la premiere fois */
      else
 inserer(tete, objet);  
 
      printf("\ncontinuer ? :" );  
      scanf(" %c", &rep);  
      }  
   getch();  
 
   /* un peu de clean up de ta liste chainee devrait te faire un bon exercice en plus */
 
   exit (0);
   }  
 
 
 
article* creer()  
   {  
   article* objet;  
   objet = (article*)malloc(sizeof(article));
   if (!object)
     {
       /* tu ecris un message d'erreur ... ou tu apelles une routine ad hoc */
       /* et tu appelles une routine qui desalloue ta structure si tu veux faire propre */
       exit (-1);
     }
   /* maintenant, en sortie de creation, tu seras sur d'avoir un article alloue */
   /* objet->nom=(char*)malloc(sizeof(char)); pas utile a ce stade, a allouer a l'utilisation effective */
   /* objet->ref=(char*)malloc(sizeof(char)); pas utile a ce stade, a allouer a l'utilisation effective */
   objet->nom = NULL;
   objet->ref = NULL;
   objet->suivant = NULL;  
   return objet;  
   }  
 
 
void inserer(article* t, article *o)  
   {  
   article* cursor = detection(t,o->nom);  
   preinsert(cursor,o);  
   }  
 
void preinsert(article *t, article *o)  
   {  
     /* o->suivant = t->suivant; // c'est la qu'il y a erreur  */
     if (t->suivant)
       o->suivant = t->suivant;
     t->suivant = o;  
   }  
 
article* detection(article* t, char *nom)  
{  
  article* lire = t;  
     
  while ( lire && (strcmp(lire->nom, nom)<= 0))  
    lire = lire->suivant;  
 
  return lire;  
}  
 
 
Bon, en fait, ce qui ne va pas, c'est ta fonction detection:
 Si tu trouves, tu renvoies l'element de ta liste chainee deja trouve et si tu trouves pas, tu renvoies NULL.
Ca pose probleme au retour dans inserer qui a pas prevu que ca retourne NULL.
 Je suppose que ce que tu veux faire c'est:  
 
void inserer(article* t, article *o)  
   {  
   article* cursor = detection(t,o->nom); /* o est non NULL et on ne compare que le nom */
 
   if (cursor)
      preinsert(cursor,o);
   else
      {
        cursor = t; /* on se replace en tete */
        while (cursor->suivant) /* on va a la fin de la lc */
             cursor= cursor->suivant;
        cursor->suivant = o;
      }  
   }  
 
A+,
 

 


--Message édité par gilou--


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 14-02-2001 à 12:01:20    

/* un peu de clean up de ta liste chainee devrait te faire un bon exercice en plus */
 
Oh oui ça être bon !!!!!! En itératif, récursif et récursif terminal tant qu'à faire :D


---------------
"If you can walk away from a landing, it's a good landing. If you use the airplane the next day, it's an outstanding landing." - Chuck Yeager. | Chaîne YT | Photos
Reply

Marsh Posté le 14-02-2001 à 12:04:48    

Le coup du malloc inutile (un char) dans la creation, puis l'espoir que scanf allait mettre la chaine a cet emplacement avec ses petits bras muscles, ca c'est typique comme erreur de debutant.
On est tous passe par ce genre d'erreurs.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 14-02-2001 à 12:47:44    

Un grand merci, je pars en vacances avec ma disquette de sources et je vais potasser tout ca la bas ! Encore merci de m'avoir accordé de votre temps.

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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