Algo1 Soutien S01 : Différence entre versions

De Ensiwiki
Aller à : navigation, rechercher
m (A déprotégé « Algo1 Soutien S01 »)
 
Ligne 1 : Ligne 1 :
 +
{{Maintenance uniquement par enseignants}}
 
== Affichages de suites ==
 
== Affichages de suites ==
  

Version actuelle en date du 11 avril 2017 à 09:04

AttentionCette page est maintenue uniquement par les enseignants. Afin de ne pas perturber le déroulement des cours, elle n'a pas vocation à être modifiée par les élèves. Mais si vous avez des modifications à proposer, merci d'en discuter ou d'envoyer un e-mail aux auteurs de la page (cf. historique)

Affichages de suites

Vous avez déjà travaillé sur cet exercice en TP encadré, il s'agit de l'exercice P4.

Le but de cet exercice est de travailler sur des itérations très simples pour commencer.

Factorielle

Commencez par compléter le programme ci-dessous en implantant la fonction Fact qui calcule la factorielle de l'entier naturel passé en paramètre. On demande une implantation itérative (et pas récursive) pour la fonction Fact.

with Ada.Text_IO, Ada.Integer_Text_IO;
use Ada.Text_IO, Ada.Integer_Text_IO;

procedure S01_E1 is

    function Fact(N: Natural) return Positive is
    ...

    N: Natural;

begin
    Put("Entrer un naturel : "); Get(N);
    Put("Fact("); Put(N, WIDTH=>0); Put(") = ");
    Put(Fact(N), WIDTH=>0); New_Line;
end;

Il est important de rappeler que les noms des fichiers contenant des programmes Ada doivent être complètement en minuscules. Ici, vous appellerez votre fichier s01_e1.adb.

Modifiez ensuite le programme principal pour qu'il n'affiche non plus seulement Fact(N) mais la suite des valeurs de Fact(I) pour tous les I entre 0 et N inclus.

Fibonacci

Reprendre le même exercice pour la suite de Fibonacci : commencer par implanter une fonction calculant Fibo(N) pour un N donné, puis ajouter une boucle pour afficher la suite de toutes les valeurs de la suite de Fibonacci pour I allant de 0 à N inclus.

Analyse d'une suite d'entiers

Cet exercice a été traité en TP encadré sous le nom d'exercice P7.

Le but de cet exercice est d'écrire un premier module (package) simple et d'apprendre à l'utiliser comme une boite noire.

Spécification du module

Lorsqu'on demande d'écrire un module, on donne toujours sa spécification sous la forme de son interface. L'interface est le "contrat" qui liste les actions fournies par le module et comment on doit les utiliser.

Ici, on donne l'interface suivante pour le module SuiteEntiers :

package SuiteEntiers is
    -- Initialise le module et entre le premier entier
    procedure Init(X: Integer);
    -- Entre un nouvel entier
    procedure Entre(X: Integer);
    -- Renvoie le nombre d'entiers entrés
    function NbEntrees return Integer;
    -- Renvoie la somme des entiers entrés
    function Somme return Integer;
    -- Renvoie vrai ssi la suite des entiers
    --   entrées est strictement croissante
    function EstCroissante return Boolean;
    -- Renvoie l'entier maximum parmi ceux entrés
    function Maximum return Integer;
    -- Renvoie l'indice (en commençant à 1)
    --   de la première occurrence du maximum
    function PremMax return Integer;
    -- Renvoie l'indice de la dernière occurrence du maximum
    function DerMax return Integer;
    -- Renvoie le nombre d'occurrences du
    --   maximum dans la suite
    function NbrMax return Integer;
end SuiteEntiers;

Recopiez cette interface dans un fichier appelé forcément suiteentiers.ads (il est important d'écrire les noms de fichiers tout en minuscules).

Programme principal

Une fois qu'on a l'interface d'un module, on peut l'utiliser même sans savoir comment il est implanté. On va donc écrire le programme principal utilisant le module SuiteEntiers avant d'implanter les procédures qui le compose.

Complétez le programme principal ci-dessous en écrivant une boucle qui lit des entiers, les enregistre dans le module (en utilisant Init pour le premier et Entre pour les suivants) et s'arrête dès qu'on saisit un entier négatif :

with Ada.Text_IO, Ada.Integer_Text_IO, SuiteEntiers;
use Ada.Text_IO, Ada.Integer_Text_IO, SuiteEntiers;

procedure S02_E1 is

    X: Integer;

begin
    Put_Line("Entrer les entiers positifs :");
    ...
    if (NbEntrees > 0) then
        Put("Moyenne = "); Put(Somme / NbEntrees, WIDTH=>0); New_Line;
    end if;
    Put_Line("Suite croissante : " & Boolean'Image(EstCroissante));
    Put("Maximum = "); Put(Maximum, WIDTH=>0); New_Line;
    Put("Premiere occurence = "); Put(PremMax, WIDTH=>0); New_Line;
    Put("Derniere occurence = "); Put(DerMax, WIDTH=>0); New_Line;
    Put("Nombre d'occurences = "); Put(NbrMax, WIDTH=>0); New_Line;
end;

On voit que le programme principal va utiliser les procédures du module pour afficher des statistiques sur les données entrées, une fois la boucle terminée.

Implantation du module

On va finalement implanter le module SuiteEntiers. Pour cela, on peut se représenter le module comme une machine à état simple, composée :

  • de variables globales, dont l'ensemble constitue l'état de la machine ;
  • de fonctions de sélection, dont le rôle est juste de renvoyer la valeur de telle ou telle variable de l'état global (et notamment pas de modifier cet état) ;
  • de procédures de mise à jour de l'état, qui vont influer sur les variables globales du module.

Dans le cadre de cet exercice, les procédures de mise à jour sont Init et Entre, et toutes les autres primitives à implanter sont des fonctions de sélection.

Vous devez donc compléter le corps du module SuiteEntiers que l'on donne ci-dessous :

package body SuiteEntiers is

    Nb: Integer;

    procedure Init(X: Integer) is
    begin
        Nb := 1;
        ...
    end;

    procedure Entre(X: Integer) is
    begin
        Nb := Nb + 1;
        ...
    end;

    function NbEntrees return Integer is
    begin
        return Nb;
    end;

    function Somme return Integer is
    ...

    function EstCroissante return Boolean is
    ...

    function Maximum return Integer is
    ...

    function PremMax return Integer is
    ...

    function DerMax return Integer is
    ...

    function NbrMax return Integer is
    ...

end SuiteEntiers;

On a implanté la fonction NbEntrees comme exemple de ce qu'il faut faire : on note bien qu'elle ne fait que renvoyer la valeur de la variable globale (privée, c'est à dire interne) Nb sans la modifier : ce sont les procédures de mise à jour Init et Entre qui modifient cette variable.

Vous devez compléter le corps du module, en implantant les fonctions restantes. Pour cela, vous devrez à chaque fois :

  • définir une ou plusieurs variables globales pour intégrer dans l'état du module les informations nécessaires à la fonction implantée ;
  • modifier Init et Entre pour mettre à jour l'état du module en fonction des valeurs entrées ;
  • implanter la fonction de sélection voulue, qui ne doit faire que renvoyer la valeur de la variable interne correspondant à son rôle.