PROGRAM MOYENNE;

(* Pour l'‚nonc‚ de ce programme, voir la proc‚dure AVERTIS
   Principe du programme :
   montrer qu'une mˆme proc‚dure (LIS) peut ˆtre ex‚cut‚e pour faire 4 choses diff‚rentes :
   lire la borne inf‚rieure des nombres … lire
   lire la borne sup‚rieure des nombres … lire
   lire le nombre bidon qui provoquera l'arrˆt des lectures
   lire tous les nombres dont le programme fera la moyenne. *)

USES CRT;

VAR BORNE_INF,       (* qui contiendra le nombre limite inf‚rieur de tous les nombres … lire *)
    BORNE_SUP,       (* qui contiendra le nombre limite sup‚rieur de tous les nombres … lire *)
    BIDON,           (* qui contiendra le nombre bidon qui signalera la fin de la lecture des nombres*)
    COMPTEUR,        (* qui va permettre de compter les nombres lus *)
    SOMME,           (* qui va permettre de faire la somme de tous les nombres lus *)
    NOMBRE:          (* qui contiendra le nombre lu *)
              INTEGER;
    MOYENNE:         (* qui va permettre de calculer la moyenne des nombres lus *)
              REAL;

PROCEDURE AVERTIS;
          BEGIN
          WRITELN ('Ce programme lit des nombres entiers jusqu''… rencontrer un nombre bidon');
          WRITELN ('donn‚ au pr‚alable par l''utilisateur. Le programme affiche alors');
          WRITELN ('la moyenne des nombres lus sans tenir compte du nombre bidon.');
          WRITELN ('Tous les nombres lus (y compris le bidon) doivent ˆtre compris');
          WRITELN ('entre deux nombres limites donn‚s au pr‚alables par l''utilisateur.');
          WRITELN;
          END;

PROCEDURE LIS (QUOI: STRING; MIN, MAX: INTEGER; VAR NOMBRE: INTEGER);
          (* QUOI va contenir la chaŒne de caractŠres signalant ce qu'on demande
             MIN va contenir la borne inf‚rieure du nombre … lire
             MAX va contenir la borne sup‚rieure du nombre … lire
             NOMBRE va retourner au pp le nombre lu contenu entre les deux bornes MIN et MAX comprises *)

          VAR VALEUR: LONGINT; (* Si on lit directement un entier "normal", tout d‚passement de capacit‚ des entiers
                                  (moins de -32768 ou plus de 32767) sera ramen‚ automatiquement et avec une erreur
                                  dans ces limites. Cette lecture erronn‚e n'aurait aucun sens. On acceptera donc
                                  un entier long afin de pouvoir v‚rifier s'il y a d‚passement ou pas.
                                  S'il n'y a pas d‚passement, il suffira d'affecter une variable entiŠre "normale"
                                  avec l'entier long pour que la transformation soit faite (sans erreur cette fois
                                  puisque le non d‚passement de capacit‚ aura ‚t‚ v‚rifi‚). Le passage direct
                                  d'un entier long en paramŠtre variable vers un entier normal n'est pas accept‚. *)

          BEGIN
          WRITELN ('Donne-moi ',QUOI);
          WRITE   ('(un entier entre ',MIN,' et ',MAX,' compris) : ');
          READLN  (VALEUR);
          WHILE (VALEUR < MIN) OR (VALEUR > MAX) DO
          (* Ecrire WHILE NOT (NOMBRE IN [MIN..MAX]) DO ne fonctionne pas. Pourquoi ? *)
                BEGIN
                WRITE  ('Erreur, le nombre n''est pas dans les limites permises. Recommence : ');
                READLN (VALEUR);
                END;
          NOMBRE := VALEUR;
          WRITELN;
          END;

BEGIN     (* du programme principal *)
CLRSCR;   (* pour effacer l'‚cran *)
AVERTIS;
LIS ('la valeur du plus petit des nombres … lire', -32768, 32767, BORNE_INF);
LIS ('la valeur du plus grand des nombres … lire', BORNE_INF, 32767, BORNE_SUP);
LIS ('le nombre bidon qui provoquera l''arrˆt de la lecture', BORNE_INF, BORNE_SUP, BIDON);
COMPTEUR := 0;
SOMME := 0;
REPEAT
      LIS ('un nombre', BORNE_INF, BORNE_SUP, NOMBRE);
      INC (COMPTEUR);
      SOMME := SOMME + NOMBRE;
UNTIL NOMBRE = BIDON;
IF COMPTEUR = 1 THEN
   (* Evite une division par z‚ro *)
   WRITELN ('Aucun nombre lu (mis … part le nombre bidon), pas de calcul de moyenne.')
ELSE
    BEGIN
    MOYENNE := (SOMME - BIDON)/(COMPTEUR - 1);
    WRITELN ('La moyenne des nombres lus, sans compter le bidon, est ',MOYENNE:13:6);
    END;
READLN;
END.
