Rangement d'une liste

Rangement d'une liste - Ada - Programmation

Marsh Posté le 02-06-2009 à 19:47:43    

Bonsoir,
 
C'est encore moi, avec une nouvelle fois un problème sur les listes. J'explique mon sujet. Je cherche à écrire un programme qui range des valeurs saisies par un utilisateur au fur et à mesure dans une liste chaînée. Les valeurs négatives sont rangées en début de liste, et les valeurs positives sont rangées en fin de liste; la valeur 0 n'est pas rangée dans la liste, la saisie se termine quand l'utilisateur rentre 0.
 
Par exemple:
 
Si l'utilisateur fournit successivement les valeurs 4, -5, 8, 2, -3, -9, 1, 0, on cherche à obtenir l'affichage suivant:
 
"La liste contient les valeurs suivantes: -9 -3 -5 4 8 2 1."
 
Pour l'instant, voici ce que j'ai fait (je n'ai pas encore fait la procédure de saisie, il faut d'abord que le reste fonctionne, c'est plus important à mon avis):
 

Code :
  1. with Ada.Text_IO, Ada.Integer_Text_IO;
  2. use Ada.Text_IO, Ada.Integer_Text_IO;
  3. procedure Prog is
  4.  
  5.    -- Déclaration des types et sous-types
  6.  
  7.    subtype Entiers is Integer range -50..50;
  8.  
  9.    type Element;
  10.  
  11.    type Liste is access Element;
  12.  
  13.    type Element is record
  14.      
  15.       Valeur: Entiers;
  16.       Suivant: Liste;
  17.      
  18.    end record;
  19.  
  20.    -- Sous-programme qui range une valeur donnée dans une liste: les élements négatifs à gauche, les positifs à droite
  21.  
  22.    procedure Ranger_Dans_Liste (Ma_Valeur: in Entiers; Ma_Liste: in out Liste) is
  23.      
  24.       Aux: Liste := Ma_Liste;
  25.      
  26.    begin
  27.      
  28.       if Ma_Liste = null then
  29.        
  30.          Ma_Liste := new Element'(Ma_Valeur,null);
  31.        
  32.       else
  33.        
  34.          if Ma_Valeur < 0 then
  35.            
  36.             if Aux.All.Valeur > 0 then
  37.              
  38.                Aux := new Element'(Ma_Valeur,Aux);
  39.              
  40.             elsif Aux.All.Valeur < 0 then
  41.              
  42.                Aux := new Element'(Ma_Valeur, Aux.All.Suivant);
  43.              
  44.             end if;
  45.            
  46.          elsif Ma_Valeur > 0 then
  47.            
  48.             if Aux.All.Valeur > 0 then
  49.              
  50.                Aux := new Element'(Ma_Valeur, Aux.All.Suivant);
  51.              
  52.             elsif Aux.All.Valeur < 0 then
  53.              
  54.                Aux := new Element'(Ma_Valeur, Aux);
  55.              
  56.             end if;
  57.            
  58.          end if;
  59.        
  60.       end if;
  61.      
  62.    end Ranger_Dans_Liste;
  63.  
  64.    -- Sous-programme d'affichage de la liste (ordre de saisie)
  65.  
  66.    procedure Afficher_Liste (Ma_Liste: in Liste) is
  67.      
  68.       Aux: Liste := Ma_Liste;
  69.  
  70.    begin
  71.      
  72.       Put("Valeurs contenues dans la liste: " );
  73.       new_line(2);
  74.      
  75.       while Aux /= null loop
  76.        
  77.          Put(Aux.All.Valeur,0);
  78.          new_line;
  79.          Aux := Aux.All.Suivant;
  80.        
  81.       end loop;
  82.      
  83.    end Afficher_Liste;
  84.  
  85.    -- Declaration du programme general
  86.  
  87.    Ma_Liste: Liste;
  88.  
  89. begin
  90.  
  91.    Ma_Liste := new Element'(-3,new Element'(-1, new Element'(4,null)));
  92.    Ranger_Dans_Liste(-2, Ma_Liste);
  93.    Afficher_Liste(Ma_Liste);
  94.  
  95. end Prog;


 
Pour une liste vide, pas de problèmes, ça fonctionne! :bounce:  
Dans le cas contraire, ça ne va plus du tout par contre: j'ai par exemple essayé de ranger une valeur négative (-2), dans une liste donnée: -3 -1 4, en vain. Voyez-vous où sont les problèmes? J'ai essayé de m'illustrer le problème, mais je ne parviens pas à voir ce qui ne va pas. Si vous avez des questions relatives à mon code, n'hésitez surtout pas! En espérant que vous pourrez me guider, merci d'avance! ;)

Reply

Marsh Posté le 02-06-2009 à 19:47:43   

Reply

Marsh Posté le 11-06-2009 à 12:49:07    

Pourquoi ne pas utiliser les conteneurs standard de Ada.Containers comme par exemple Ada.Containers.Ordered_Sets qui est triéée?
 
Bah je me doute que c'est dans un but pédagogique, alors ok.

Reply

Marsh Posté le 11-06-2009 à 13:51:07    

Ton erreur viens du fait que ta procédure Ranger_Dans_Liste, ne parcours pas ta liste en profondeur, elle se limite à visiter le 1er ou le 2ème élement de ta liste. Il faut utiliser une boucle ou faire de ta procédure une procédure récursive.
 
A part cela, ta procédure Ranger_Dans_Liste fais trop usine-à-gaz, il y a plus simple. Tu as aussi la version procédure récursive, que je n'indique pas ici tellement elle est simple (c'est un cas d'école), je pense que tu pourras la faire facilement une fois que tu auras compris le principe de ma version ci-dessous.
 
Petite remarque: Comment aie-je pu écrire mon exemple ci-dessous? Simple l'idée est la même que la procédure Afficher_Liste.
 

Code :
  1. with Ada.Text_IO, Ada.Integer_Text_IO;
  2. use Ada.Text_IO, Ada.Integer_Text_IO;
  3. procedure Prog is
  4.  
  5.    -- Déclaration des types et sous-types
  6.  
  7.    subtype Entiers is Integer range -50..50;
  8.  
  9.    type Element;
  10.  
  11.    type Liste is access Element;
  12.  
  13.    type Element is record
  14.      
  15.       Valeur: Entiers;
  16.       Suivant: Liste;
  17.      
  18.    end record;
  19.  
  20.    -- Sous-programme qui range une valeur donnée dans une liste: les élements négatifs à gauche, les positifs à droite
  21.  
  22.    procedure Ranger_Dans_Liste (Ma_Valeur: in Entiers; Ma_Liste: in out Liste) is
  23.       type Adr_Liste is not null access all Ma_Liste;
  24.      
  25.       Res: aliased Liste := Ma_Liste;
  26.       Aux: Adr_Liste := Res'Access;
  27.      
  28.    begin
  29.      
  30.       if Ma_Liste = null then
  31.        
  32.          Ma_Liste := new Element'(Ma_Valeur,null);
  33.        
  34.       else
  35.        
  36.          while (Aux.All /= null) and (Aux.All.All.Valeur < 0) loop
  37.             Aux := Aux.All.All.Suivant'Access;
  38.        
  39.          end loop;
  40.          Aux.All := new Element'(Ma_Valeur, Aux.All);
  41.          Ma_Liste := Res;
  42.       end if;
  43.      
  44.    end Ranger_Dans_Liste;
  45.  
  46.    -- Sous-programme d'affichage de la liste (ordre de saisie)
  47.  
  48.    procedure Afficher_Liste (Ma_Liste: in Liste) is
  49.      
  50.       Aux: Liste := Ma_Liste;
  51.  
  52.    begin
  53.      
  54.       Put("Valeurs contenues dans la liste: " );
  55.       new_line(2);
  56.      
  57.       while Aux /= null loop
  58.        
  59.          Put(Aux.All.Valeur,0);
  60.          new_line;
  61.          Aux := Aux.All.Suivant;
  62.        
  63.       end loop;
  64.      
  65.    end Afficher_Liste;
  66.  
  67.    -- Declaration du programme general
  68.  
  69.    Ma_Liste: Liste;
  70.  
  71. begin
  72.  
  73.    Ma_Liste := new Element'(-3,new Element'(-1, new Element'(4,null)));
  74.    Ranger_Dans_Liste(-2, Ma_Liste);
  75.    Afficher_Liste(Ma_Liste);
  76.  
  77. end Prog;


 
Ce qui est beau ce que le nombre de comparaison est limité à la liste, nul besoin de tester la valeur de l'argument Ma_Valeur passé à la procédure Ranger_Dans_Liste. Mais j'avoue l'utilisation d'un type accès d'un accès (type Adr_Liste) est un peu limite, et propose donc une solution qui peut être pris pour de l'Ada bon marché et peut mal passer pour des puristes de l'Ada, car cette solution est plus inspirée du langage C ou du C++.
 
La meilleure solution est d'utiliser des objets et de convertir le type Liste en tagged record. La manipulation de la liste chainée gagnerai en simplicité du code et permettrait au code d'etre plus dans la philosophie Ada en évitant ce type Adr_Liste.
 
sinon une autre version tout aussi simple serait:

Code :
  1. if négatif then
  2.   mettre au début;
  3. else
  4.   aller à la fin de la liste;
  5.   mettre à la fin;
  6. end if;


 
ou

Code :
  1. Res: Liste := Ma_Liste;
  2.    Aux: Liste := Ma_Liste;
  3. begin
  4.    ( .... )
  5.    if Ma_Valeur < 0 then
  6.       Ma_Liste:= new Element'(Ma_Value, Res);
  7.    else
  8.       while Aux.All.Suivant /= null loop
  9.          Aux:= Aux.All.Suivant;
  10.       end loop;
  11.      
  12.       Aux.All.Suivant:= new Element'(Ma_Valeur, null);
  13.       Ma_Liste:= Res;
  14.    end if;
  15.    ( .... )
  16.  
  17. end;


Message édité par Corebreaker le 11-06-2009 à 14:04:23
Reply

Sujets relatifs:

Leave a Replay

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