Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1133 connectés 

  FORUM HardWare.fr
  Programmation

  [C] Listes chainées - le retour -

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[C] Listes chainées - le retour -

n°16817
Evadream -​jbd-
Posté le 03-03-2001 à 16:44:48  profilanswer
 

Pour rappel, voici le premier TOPIC ou on m'a BEAUCOUP AIDE  
( http://forum.hardware.fr/sqlforum/ [...] ache=cache )
 , et je remercie une nouvelle fois de plus tout le monde.
 
Voila, j'ai repris tout ca, et mon insertion ds l'ordre lexicographique ne fonctionne pas. Je cherche à reperer ou insérer mon article ds ma LC via la fonction détection et je l'insere via la fonction preinsert ( ie : je veux inserer au bon endroit à chaque fois et ne pas faire appel à une fonction de tri total de ma LC ). Le pb, c que ca marche pas. La tete ne rentre pas ds mon tri, et la suite est mal trié, je ne comprends pas. J'ai vraiment essayé bcp de choses, et mon algo me semble correct. Si pouviez y jeter un oeil ca me debloquerait je pense. Merci ! @+
 
Voici le code :  
 
 
#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);
void affiche(article *t);
 
 
 
void main()
   {
   article* tete = NULL;
   article* objet;
   int i=0;
   char rep='o';      
   char buffer[255];  
 
   printf("Creation d'une liste chainee\n" );
   getch();
 
   //while(rep=='o' )
   while ( i < 5 )
      {
      objet=creer();
      //clrscr();
      printf("Donner son nom : " );
 
      scanf(" %s", buffer);
      (*objet).nom = strdup(buffer);
 
      if ( tete==NULL ) tete = objet;  
      else inserer(tete, objet);
      i++;
      //printf("\ncontinuer ? :" );
      //scanf(" %c", &rep);
      }
   getch();
   affiche(tete);
   getch();
 
   }
 
 
 
article* creer()
   {
   article* objet;
   objet = (article*)malloc(sizeof(article));
   if ( objet==NULL )
     {
       printf("Probleme d'allocation memoire !" );
       getch();
     }
   (*objet).nom = NULL;
   (*objet).ref = NULL;
   (*objet).suivant = NULL;
   return objet;
   }
 
void preinsert(article *t, article *o)
   {
   if ( (*t).suivant != NULL )
       {
       (*o).suivant = (*t).suivant;
       }
     (*t).suivant = o;
   }
 
article* detection(article* t, char *nom)
   {
   article* lire = t;
 
   while( lire && ( strcmp( nom,(*lire).nom ) >= 0 ) )
       {
       lire = (*lire).suivant;
       }
       return lire;
   }
 
void inserer(article* t, article *o)
   {
   article* cursor = detection ( t, (*o).nom );
 
   if ( cursor != NULL )
      {
      preinsert ( cursor , o);
      }
    else
       {
         cursor = t; /* on se replace en tete */
         while( (*cursor).suivant != NULL) /* on va a la fin de la lc */
          {
                cursor= (*cursor).suivant;
                }
        (*cursor).suivant = o;
       }
   }
 
void affiche(article *t)
   {
   article *lire=t;
   clrscr();
 
   printf("Etat du stock : \n" );
 
 while( ( lire!=NULL ) )
    {
        printf("\nNom : %s", (*lire).nom);
      //printf("\nReference : %s", (*lire).ref);
      //printf("\nPrix : %4.2lf", (*lire).prix);
      //printf("\nReste : %d", (*lire).reste);
        lire=(*lire).suivant;
      }
 
   printf("\nFin du stock\n\n" );
   getch();
   }

 

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

mood
Publicité
Posté le 03-03-2001 à 16:44:48  profilanswer
 

n°16818
Evadream -​jbd-
Posté le 03-03-2001 à 16:51:28  profilanswer
 

A noter que je travaille sous Borland C++ 5.

n°16822
BifaceMcLe​OD
The HighGlandeur
Posté le 03-03-2001 à 17:06:52  profilanswer
 

Je regarde ça.
 
Avant une analyse plus détaillée, je ferai juste 2 remarques.
1 - Écris "objet->suivant" plutôt que "(*objet).suivant", c'est plus facile à lire... ;)
2 - Tu as besoin d'aller au début et à la fin de ta liste chaînée. Alors je te conseille de créer une deuxième structure "ListeArticle" comme suit :
    typedef struct _ListeArticle {
        article*  tete;
        article*  queue;
    } ListeArticle;
 
Deux avantages :
1 - Quand un paramètre d'une de tes fonctions est censé représenter une liste d'articles, il sera de type "ListeArticles" plutôt que "article". Ca éclaircira grandement tes algorithmes.
2 - Plus besoin de parcourir la liste pour atteindre sa fin : tu as désormais un accès direct !
 
Par ailleurs, ton preinsert(), je l'aurais écrit plutôt comme suit :
    void preinsert(article *t, article *o)
    {
        if (t != NULL) {
            o->suivant = t->suivant;
            t->suivant = o;
        }
    }
 
Ici, ce n'est pas important si t->suivant est NULL. Ce qu'il faut, c'est éviter à tout prix de déréférencer un pointeur NULL, or les seuls pointeurs que tu déréférences ici, c'est o et t. Mais t->suivant n'est pas déréférencé, lui.

n°16823
Evadream -​jbd-
Posté le 03-03-2001 à 17:09:21  profilanswer
 

Ok, je prends note, je regarde de mon coté, merci du temps que tu consacres.

n°16824
verdoux
And I'm still waiting
Posté le 03-03-2001 à 17:22:41  profilanswer
 

Le pb qu'il y a, en plus des remarques précédentes, est que:
- preinsert(t, o) insère o juste APRES t
- détection retourne un pointeur sur l'objet AVANT lequel il faudrait faire l'insertion.

n°16825
BifaceMcLe​OD
The HighGlandeur
Posté le 03-03-2001 à 17:32:45  profilanswer
 

Merci, Verdoux, tu as été plus rapide que moi. Pour le coup de preinsert(), je l'avais vu, mais pour detection, il a fallu que j'exécute le programme.
 
Voici donc ce que je te propose, Evadream :
 
#include <stdio.h>
#include <conio.h>
#include <alloc.h>
#include <string.h>
 
typedef struct _Article {
    struct _Article*  suivant;
    char*             nom;
    char*             ref;
    double            prix;
    int               reste;
} Article;
 
typedef struct _ListeArticle {
    Article*  tete;
    Article*  queue;
} ListeArticle;
 
 
ListeArticle* creerListe();
 
Article* creer();
Article* detection(ListeArticle* liste, char* nom);
void     inserer  (ListeArticle* liste, Article* o);
void     preinsert(Article* t, Article* o, ListeArticle* liste);
void     affiche  (ListeArticle* liste);
 
 
 
void main()
{
   ListeArticle*  liste = creerListe();
   Article*       objet;
   int            i   = 0;
   char           rep = 'o';
   char           buffer[255];
 
   printf("Creation d'une liste chainee\n" );
   getch();
 
   //while (rep == 'o') {
   while (i < 5) {
      objet = creer();
      //clrscr();
      printf("Donner son nom : " );
 
      scanf(" %s", buffer);
      objet->nom = strdup(buffer);
 
      inserer(liste, objet);
 
      i++;
      //printf("\ncontinuer ? :" );
      //scanf(" %c", &rep);
   }
 
   getch();
   affiche(liste);
   getch();
}
 
 
ListeArticle* creerListe()
{
   return (ListeArticle*) calloc(1, sizeof(ListeArticle));
}
 
Article* creer()
{
   Article*  objet = (Article*) malloc(sizeof(Article));
 
   if (objet == NULL) {
       printf("Probleme d'allocation memoire !" );
       getch();
   }
 
   objet->nom     = NULL;
   objet->ref     = NULL;
   objet->prix    = 0.0;
   objet->reste   = 0;
   objet->suivant = NULL;
 
   return objet;
}
 
void preinsert(Article* t, Article* o, ListeArticle* liste)
{
    if (t != NULL) {
        o->suivant = t->suivant;
        t->suivant = o;
 
        if (liste->queue == t) {
            liste->queue = o;
        }
    }
}
 
Article* detection(ListeArticle* liste, char* nom)
{
    Article*  cursor = liste->tete;
    Article*  next   = cursor;
 
    while (next != NULL  &&  strcmp(next->nom, nom) < 0) {
        cursor = next;
        next   = next->suivant;
    }
 
    return cursor;
}
 
void inserer(ListeArticle* liste, Article* o)
{
    Article*  cursor;
 
    if (liste->tete == NULL) {
        liste->tete  = o;
        liste->queue = o;
 
        return;
    }
 
    cursor = detection(liste, o->nom);  
 
    if (cursor != NULL) {
        preinsert(cursor, o, liste);
    }
    else {
        liste->queue->suivant = o;
        liste->queue          = o;
    }
}
 
void affiche(ListeArticle* liste)  
{
   Article*  cursor = liste->tete;
 
   clrscr();
 
   printf("Etat du stock : \n" );
 
   while (cursor != NULL) {
       printf("\nNom : %s", cursor->nom);
       //printf("\nReference : %s", cursor->ref);
       //printf("\nPrix : %4.2lf", cursor->prix);
       //printf("\nReste : %d", cursor->reste);
 
       cursor = cursor->suivant;
   }
 
   printf("\nFin du stock\n\n" );  
   getch();  
}

n°16827
BifaceMcLe​OD
The HighGlandeur
Posté le 03-03-2001 à 17:35:05  profilanswer
 

Et renommer preinsert() en postinsert() ou insert() tout court, bien sûr...

n°16866
Evadream -​jbd-
Posté le 03-03-2001 à 23:28:36  profilanswer
 

Oulala, merci ! Ca epure bien les choses. Je vais analyser tout ca ! Sinon, le probleme de début n'est pas résolu : l'insertion ds l'ordre lexicographique, ca marche pas. Par exemple, lorsque l'on rentre ds cette ordre : z,d,y,e,b on obtient z,b,e,y,d. Et pourtant, l'algo me semble juste.
 
En tout cas, merci bcp à vous deux.

n°16868
verdoux
And I'm still waiting
Posté le 03-03-2001 à 23:58:11  profilanswer
 

Oui le pb est qu'avec le code proposé on peut pas modifier le premier de la liste.

 

--Message édité par Verdoux--

n°16870
Evadream -​jbd-
Posté le 04-03-2001 à 00:34:41  profilanswer
 

Ah bon ? Mmm, j'ai du mal là. Et puis ca trie mal apres aussi, pas slt le premier de la liste. En tout cas, c plus propre qu'avant :)  
 
Je vois pas pkoi on peut pas bouger le premier de la liste et que ca trie mal apres, mes milliers de dessins sur la meme feuille de papier m'ont pourtant toujours amene à cette solution. Je vois pas comment faire, et puis ce tri, ca commence m'enerve, je me bloque l'esprit dessus depuis 1 semaine, tjs le meme resultat, un truc qui trie pas ;) Le code de BifaceMcLeOD ( encore merci ) avec son autre typedef simplifie enormement la vision de la chose et rend le mecanisme du prog bcp plus simple à comprendre.  
 
OUin =)

mood
Publicité
Posté le 04-03-2001 à 00:34:41  profilanswer
 

n°16871
verdoux
And I'm still waiting
Posté le 04-03-2001 à 00:41:14  profilanswer
 

Avec la séquence que t'as rentrée, c'est normal.
D'abord z en tête.
Ensuite on rentre d, on compare à z et là on se dit qu'il faut l'insérer là, mais il est inséré APRES.
Ensuite y, on compare à z et comme le test est tout de suite vérifié (y<z), on l'insère juste après z et avant d.
En fait comme toutes les lettres entrantes sont plus "petites" que z, elles sont insérees juste après z, en poussant celle déjà entrées.
 

 


--Message édité par Verdoux--

n°16885
BifaceMcLe​OD
The HighGlandeur
Posté le 04-03-2001 à 03:55:04  profilanswer
 

Bon, j'espère que je ne vais pas dire de bêtises, là...
 
Ton problème, c'est que tu n'arrives pas à insérer avant. Or pour pouvoir le faire, tu as besoin de pouvoir modifier la cellule précédente (ou plus exactement, le pointeur vers la cellule courante, qui est soit dans la cellule précédente, soit, s'il y en a pas, le pointeur sur la tête de liste). Alors que tu n'as accès qu'à la cellule courante et la cellule suivante, mais aucun moyen de remonter vers la cellule précédente. Il faut donc trouver un moyen pour pouvoir modifier cette cellule précédente (plus exactement, le pointeur qui pointe vers la cellule courante ; je sais, je me répète).
 
Tu dois pouvoir t'en sortir soit en faisant retourner un Article** à detection(), soit en faisant en sorte que ta liste chaînée soit doublement chaînée (i.e. un pointeur sur le suivant et aussi un pointeur sur le précédent).
 
Si tu choisis la solution 2, je te laisse voir comment faire (dans ce cas, inutile de modifier detection(), il est très bien comme cela).
 
Si tu choisis la solution 1, il faut que detection() renvoie un pointeur sur le pointeur qui à terme devra pointer sur la cellule à insérer.
 
Donc s'il faut insérer au début de la liste, detection() devra retourner &liste->tete. Sinon, (si je ne me suis trompé dans l'itération que fait detection) &cursor->suivant. Est-ce que c'est clair ? (je sais, là, ça commence à être assez fin...)

n°16889
Evadream -​jbd-
Posté le 04-03-2001 à 09:26:00  profilanswer
 

Je dois avouer que c'est un peu l'angoisse :)

n°16890
Evadream -​jbd-
Posté le 04-03-2001 à 10:00:45  profilanswer
 

void inserer(ListeArticle* liste, Article* o)
{
    Article*  cursor;
 
    if (liste->tete == NULL) {
        liste->tete  = o;
        liste->queue = o;
        return; // je ne comprends ce que vient faire ce return ici, et pourquoi le prog s'arrete à la deuxieme saisie si on l'enleve.
 
    }
 
Sinon, j'ai essaye avec ce que vous m'avez dit ( pointeurs de pointeurs ), j'ai un peu de mal à m'y retrouver, et puis ca le compilo à pas l'air d'aimer que je me plante, j'ai un comportement bizarre de Borland, je compile et puis y me sort un truc que j'ai pas ouvert depuis 2 mois :). J'espere que je vais y arriver
 

 


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

n°16943
BifaceMcLe​OD
The HighGlandeur
Posté le 04-03-2001 à 18:10:36  profilanswer
 

Si la liste est vide, il suffit de dire "la première et la dernière cellule de la liste sont la même cellule, celle à insérer". Et ça y est, on a fini l'insertion. Voilà à quoi sert le return : à dire "ça y est, on a fini l'insertion".
 
Maintenant, tu peux aussi l'enlever, mais il faut alors que tout le code qui suit dans la fonction inserer() soit dans un else, celui du "if (liste->tete == NULL)".
 
Sinon, la solution du double pointeur n'est pas forcément la plus simple, mais c'est sans doute celle qui te fera le plus apprendre. N'hésite pas à re-publier des morceaux de ton programme si tu ne t'en sors pas...

 

--Message édité par BifaceMcLeOD--

n°16945
Evadream -​jbd-
Posté le 04-03-2001 à 18:27:11  profilanswer
 

Ok, merci bcp !!

n°16952
verdoux
And I'm still waiting
Posté le 04-03-2001 à 19:54:40  profilanswer
 

Tu peux essayer les modifs suivantes:
ListeArticle* creerListe()  
{  
                      ListeArticle* LA;
   LA = (ListeArticle*) malloc(sizeof(ListeArticle));
   LA->tete = NULL;
   LA->queue = NULL;
   return LA;
}  
 
// fonction de comparaison, retourne un int <0, =0 ou >0
int compare_nom(char* nom1, char* nom2) {  
  return strcmp(nom1,nom2);
}
 
 
void inserer(ListeArticle* liste, Article* o) {  
                      Article  *cursor, *next;  
   
  // la liste est vide:
                      if (liste->tete == NULL) {  
                          liste->tete  = o;  
                          liste->queue = o;  
                          return;  
   }
 
  // la liste n'est pas vide, on va voir où ce placer.
   if (compare_nom(o->nom, liste->tete->nom)<0)
    {//on doit se mettre en tete
    o->suivant = liste->tete;
    liste->tete = o;
    return;
    }
    //sinon on continue
   cursor = liste->tete;
   next = liste->tete->suivant;
   while((next!=NULL) && (compare_nom(o->nom,next->nom)>0))
   {
   cursor = next;
   next = next->suivant;
   }
   //le curseur pointe maintenat sur l'article apres lequel doit se faire l'insertion
   o->suivant = cursor->suivant;
   cursor->suivant = o;
 
   //si next = null mettre à jour la queue de la liste.
   if (next==NULL) liste->queue = o;  
}

 

--Message édité par Verdoux--

n°16955
Evadream -​jbd-
Posté le 04-03-2001 à 20:12:27  profilanswer
 

Merci ! Ca fait bcp de choses en peu de temps là =]
Je vais bien analyser tout ca, comparer à ce que j'ai deja fait. Je vous tiens au courant et je vous remercie encore pour le temps que vous m'avez accordé. Bonne soirée et bon courage pour la reprise de la semaine.

n°18150
Evadream -​jbd-
Posté le 12-03-2001 à 01:25:20  profilanswer
 

Je repasse pour vous remercier, c bon c fini, j'ai compris BEAUCOUP de choses !
 
@+

n°18158
BifaceMcLe​OD
The HighGlandeur
Posté le 12-03-2001 à 01:52:24  profilanswer
 

Je suis sûr qu'il t'en reste encore à apprendre... ;)
 
Plus sérieusement, repasse quand tu veux, c'était un plaisir de répondre à tes questions. :)


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation

  [C] Listes chainées - le retour -

 

Sujets relatifs
C : comment interprête-t-il la touche Retour Arrière (backspace) ?[CSS] Listes imbriquées.
[C] Listes chainéesfaire un retour en php
liste chainees simple 
Plus de sujets relatifs à : [C] Listes chainées - le retour -


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR