Cours 6: Types articles et pointeurs.

Objectif: Type Record, composant. Paramètres record.
Exemple: date du lendemain.
Type pointeur. Type incomplet.

Le type Record permet de regrouper plusieurs objets de types différents.

Extrait du manuel de référence (RM95):


       record_type_definition ::= [[abstract] tagged] [limited] record_definition

       record_definition ::=
           record
              component_list
           end record
         | null record

       component_list ::=
             component_item {component_item}
          | {component_item} variant_part
          |  null;

       component_item ::= component_declaration | representation_clause

       component_declaration ::=
          defining_identifier_list : component_definition [:= default_expression];

Extrait du manuel de référence (RM95):


       type Date is
          record
             Day   : Integer range 1 .. 31;
             Month : Month_Name;
             Year  : Integer range 0 .. 4000;
          end record;

       type Complex is
          record
             Re : Real := 0.0;
             Im : Real := 0.0;
          end record;

       Tomorrow, Yesterday : Date;
       A, B, C : Complex;

       -- both components of A, B, and C are implicitly initialized to zero

Exemple: Calcul de la date du lendemain.


       type Nom_de_Mois is (Janvier, Fevrier, Mars, Avril, Mai, Juin,
          Juillet, Aout, Septembre, Octobre, Novembre, Decembre);
       subtype Deux_Siecles is Integer range 1901..2099;
       subtype Quantieme is Integer range 1..31;
       type Date is record
          Jour: Quantieme;
          Mois: Nom_de_Mois;
          Annee: Deux_Siecles;
       end record;
       Function Date_du_Lendemain(D: Date) return Date is
          Demain: Date;
          Fin_de_Mois: Quantieme;
          Function Bissextile(A: Deux_Siecles) return Boolean is
          --valide seulement pour A dans [1901..2099]
          --seule annee seculaire: 2000, bissextile
          begin
            return ((A mod 4) = 0);
          end Bissextile;
       begin
          case D.Mois is
             when Avril | Juin | Septembre | Novembre =>
                  Fin_de_Mois := 30;
             when Fevrier =>
               if Bissextile(D.Annee) then
                  Fin_de_Mois := 29;
               else
                  Fin_de_Mois := 28;
               end if;
             when others =>
                  Fin_de_Mois := 31;
          end case;
          if (D.Jour /= Fin_de_Mois) then
              Demain.Jour := D.Jour + 1;
              Demain.Mois := D.Mois;
              Demain.Annee := D.Annee;
          else
              Demain.Jour := 1;
              if (D.Mois /= Decembre) then
                  Demain.Mois := Nom_de_Mois'Succ(D.Mois);
                  Demain.Annee := D.Annee;
              else
                  Demain.Mois := Janvier;
                  Demain.Annee := D.Annee + 1;
              end if;
          end if;
          return Demain;
       end Date_du_Lendemain;

Une déclaration de type peut être spécifiée en deux fois.
On commence par une déclaration incomplète qui ne définit que le nom.

Extrait du manuel de référence (RM95):


       incomplete_type_declaration ::= type defining_identifier [discriminant_part];

Le type accès permet de désigner des objets (ou des sous-programmes) par leur adresse.

Extrait du manuel de référence (RM95):


       access_type_definition ::=
           access_to_object_definition
         | access_to_subprogram_definition

       access_to_object_definition ::=
           access [general_access_modifier] subtype_indication

       general_access_modifier ::= all | constant

       access_to_subprogram_definition ::=
           access [protected] procedure parameter_profile
         | access [protected] function  parameter_and_result_profile

       access_definition ::= access subtype_mark

Extrait du manuel de référence (RM95):


       type Cell;  --  incomplete type declaration
       type Link is access Cell;

       type Cell is
          record
             Value  : Integer;
             Succ   : Link;
             Pred   : Link;
          end record;

       Head   : Link  := new Cell'(0, null, null);
       Next   : Link  := Head.Succ;

Exemple: insertion en place dans une liste simplement chaînée.


       type Cellule;
       type Liste is access Cellule;

       type Cellule is record
            Valeur: Integer;
            Suivant: Liste;
       end record;
       Procedure Ajouter_en_Place(L: in out Liste; V: Integer) is
          --insérer V en place dans la liste L triée
          NL: Liste := new Cellule'(V, null);
          --new Cellule: allocation dynamique d'un objet de type Cellule
          --Cellule'(V,null): agrégat pour fixer la valeur initiale de l'objet alloué
          CL: Liste:= L;
          PL: Liste;
       begin
          if CL=null then
             L:= NL;
          else
             while (CL.Valeur <= V and then CL.Suivant /=  null) loop
               PL:= CL;
               CL:= CL.Suivant;
             end loop;
             if (CL.Valeur <= V) then --ajout en queue, après CL
               CL.Suivant:= NL;
             else --lier la fin de liste derrière la nouvelle cellule
               NL.Suivant:= CL;
               if (PL=null) then --ajout en tête
                 L:= NL;
               else --ajout au centre, entre PL et CL 
                 PL.Suivant:= NL;
               end if;
             end if;
          end if;
       end Ajouter_en_Place;