log1

Document Sample
log1 Powered By Docstoc
					I.E.P.S.C.F. Marche en Famenne                                           Langage orienté gestion ( partie 1)


1. INTRODUCTION.

1.2. Considérations générales.

L'apprentissage de la programmation pose un problème immédiat pour le professeur : quel langage choisir et sur
quel support ( système d'exploitation ) travailler ?
N'importe quel langage permet cet apprentissage. On utilisait traditionnellement le langage PASCAL pour ses
qualités suivantes :

            syntaxe très rigide mais aisément compréhensible
            programmation structurée et par modules
            possibilité de programmation orientée objet
            environnement de développement complet
            liaison naturelle avec la logique de programmation
            universellement connu et nombreux forums de développeurs

  Comme les environnements graphiques présentent de nombreux avantages par rapport aux environnements en
mode texte, j'ai choisi de travailler avec la version WINDOWS du PASCAL : DELPHI et plus spécialement sa
version 4 ( ce n'est pas la dernière ). Cette démarche présente certains inconvénients : nous entrons directement
dans la programmation modulaire et il faudra que vous acceptiez certaines contraintes ; vous comprendrez plus
tard pourquoi. Comme vous suivez parallèlement un cours de C, vous percevrez rapidement les différences
entre les deux environnements. Le fait de travailler en environnement graphique présente aussi de nombreux
avantages :

            vous disposez les objets sur la feuille où vous le souhaitez.
            vous modifiez leurs tailles, couleurs, polices d'écritures, …
            ces objets disposent de propriétés que vous pouvez aussi modifier.
            ces objets répondent à des événements ( sollicitations de la souris et du clavier ).
            convivialité des logiciels.
            échange aisé des informations (photos, sons, films, …) entre les logiciels et avec le système
             d'exploitation.

1.2. Remarques particulières concernant DELPHI.

DELPHI est un outil de développent écrit par la société INPRISE ( connue également sous le nom de
BORLAND). Cet outil est un RAD (outil de développement rapide d'applications) ou générateur automatique
d'application. Ceci signifie que :

            tout le code relatif au développement des fenêtres et objets inclus est généré automatiquement par
             le RAD.
            les contrôles syntaxiques sont automatiques.
            le débogage est facile à mettre en œuvre.
            de nombreuses librairies sont à votre disposition sur le net.

DELPHI n'est pas le seul RAD sur le marché, il en existe toute une série dont les plus connus sont VISUAL C++
et VISUAL BASIC chez MICROSOFT, C++ BUILDER chez INPRISE, WINDEV chez PCSOFT et bien
d'autres encore dont les RAD JAVA. DELPHI est un choix personnel ; vous aurez l'occasion plus tard d'en tester
d'autres et peut-être de les choisir.

Jadis, on choisissait un langage en fonction du rôle de l'application à développer ; aujourd'hui, même si c'est
encore vrai, on peut considérer que chaque RAD est capable de développer des applications de tous les types. Le
choix final est donc dicté par des considérations personnelles :

            prix du RAD
            convivialité
            préférence du langage support
            etc…



Eric.Brasseur@village.uunet.be                                                                                      1
I.E.P.S.C.F. Marche en Famenne                                            Langage orienté gestion ( partie 1)


2. NOTIONS DE BASE.

2.1. Types de variables.

Les Types Entiers.

    Déclaration         Limite inférieure       Limite supérieure         Taille en octets
shortint                              -128                      127                          1
smallint                           -32 768                   32 767                          2
longint                    -2 147 483 648             2 147 483 647                          4
byte                                      0                     255                          1
word                                      0                  65 535                          2
integer                    -2 147 483 648             2 147 483 647                          4
cardinal                                  0           4 294 967 295                          4
int64                                  -263                   263 - 1                        8


Ceux qui ont fait du PASCAL sous DOS remarqueront les changements pour les "integer" et les "cardinal".

Les Types Réels.

     Déclaration           Limite inférieure (*)            Limite supérieure           Taille en octets
real                                       2.9 * 10-39                   1.7 * 1038                     6
single                                     1.5 * 10-45                   3.4 * 1038                     4
double                                    5.0 * 10-324                  1.7 * 10308                     8
extended                                 3.4 * 10-4932                3.4 * 10-4932                    10
comp                                          -263 + 1                       263 - 1                    8
currency                 -922 337 203 685 477.5808       922 337 203 685 477.5807                       8

(*) Ces nombres peuvent êtres négatifs.

Le type Booléen. (boolean)

Il s'agit de variables qui ne peuvent prendre que les valeurs TRUE ou FALSE. En réalité, les booléens sont
pratiquement des bytes qui contiennent les valeurs 0 pour FALSE et 1 pour TRUE. Ces variables prennent très
peu de place dans la mémoire centrale et permettent de tester la réussite d'une opération.

Le type Caractères. (char)

Il s'agit d'un et un seul caractère et non d'une chaîne de caractères ( un string en anglais ).
Les données du type caractères doivent être notées entre ' '.

Le type Chaînes de caractères. (string)

Les string peuvent contenir jusqu'à 3 Go de caractères.

Le type Tableau. ( array )

Un tableau est un ensemble de variables de même type qui peuvent s'appeler par un nom unique suivi de sa
position dans le tableau.
Exemple :

type
   tab100entiers = array[1..100] of integer;
   doubletabl = array[1.25 , 1..10] of char;
var
   i, j : integer;
   points, result : tab100entiers;


Eric.Brasseur@village.uunet.be                                                                                  2
I.E.P.S.C.F. Marche en Famenne                                            Langage orienté gestion ( partie 1)


    carreau : doubletabl;
begin
  points[12] := 8;
  i := 5;
  j := 14;
  carreau[i,j] := 'W';

Il est évidemment possible de créer des tableaux à plus de 2 dimensions. Remarquez le = ( et non : ) pour la
déclaration de type.

Attention : la déclaration de type ne suffit pas : elle crée un type mais ne réserve pas d'espace en mémoire pour y
placer le tableau; il faut donc donner un autre nom pour les variables de ce type et les déclarer en variables dans
la clause var.

Le type Enregistrement. ( record )

Il s'agit certainement du type structuré le plus puissant, car on peut le construire comme on veut :

Exemple :

type
       individu = record
          nom : string[20];
          prenom : string[20];
         age : byte;
         sexe : char;
      end;
var
   ind, ind1 : individu;
begin
  ind.nom := 'DUPONT';
  ind.prenom := 'Jules';
  ind.sexe := 'M';
  ind.age := 28;
  ind1 := ind;
end.

Chaque champ du record peut être adressé par le nom du record suivi d'un point puis du nom du champ.
Il n'est pas obligatoire de respecter l'ordre des composants du record pour le remplir, ni de les remplir tous. De
plus, vous pouvez transférer directement tout le record dans un autre. Ainsi, on aura ici ind1.prenom qui
comprendra Jules.
Il est évidemment possible de construire des structures plus élaborées. On peut ainsi créer des tableaux de
records, des records contenant des tableaux ou d'autres records.


2.2. La syntaxe.

Chaque langage dispose de sa propre syntaxe. Voici les règles fondamentales :

              Les commentaires sont placés entre accolades. Le compilateur ne prendra pas en compte les
               commentaires.
              Les lignes de code doivent se terminer par un point-virgule. ( sauf…)
              ne s'attarde pas à l'indentation des lignes de code
              ne fait pas de différence entre les majuscules et les minuscules
              le nom d'un identificateur respecte les règles suivantes :
               + le premier caractère doit être une lettre ou le caractère de soulignement
               + les autres caractères peuvent être des chiffres et des lettres ou _
               + les caractères accentués sont interdits
               + ne peut être un mot réservé du PASCAL
               + doit être absolument unique


Eric.Brasseur@village.uunet.be                                                                                       3
I.E.P.S.C.F. Marche en Famenne                                         Langage orienté gestion ( partie 1)


2.3. L'environnement de travail de DELPHI.


                                                                   Nom de l'application ou du projet




                           Barres de raccourcis                    Barre des outils




                           Barre des menus déroulants



La barre des menus déroulants.

Cette barre propose plusieurs options. Quand vous en choisissez une, automatiquement, une boîte avec de
nouvelles options se déroule sous celui que vous avez activé.

La barre des raccourcis.

Elle contient toute une série de commandes des menus déroulants. Ces commandes sont directement disponibles
par un simple clic de la souris.

La barre des outils.

Elle est composée de plusieurs onglets qui contiennent chacun des composants de votre future application (
boutons, labels, …).

La fenêtre de travail. ( Fiche ).




Eric.Brasseur@village.uunet.be                                                                               4
I.E.P.S.C.F. Marche en Famenne                                             Langage orienté gestion ( partie 1)


C'est sur la fenêtre de travail que vous placerez les composants destinés à apparaître à l'écran. Il s'agit donc de la
représentation d'un écran de l'application. Pour la remplir, on sélectionne les composants dans la boîte à outils
en cliquant d'abord sur le composant puis en cliquant de nouveau à l'endroit où vous souhaitez le voir placé. Il
vous est toujours possible de le déplacer, supprimer, modifier plus tard.
Un projet peut contenir plusieurs fenêtres de travail organisées hiérarchiquement.
La fenêtre de travail est elle-même un objet que vous pouvez modifier à loisir ( elle dispose de propriétés ).

L'inspecteur d'objets.


                                             Nom du composant sur lequel vous travaillez


                                             Vous travaillez ici sur les propriétés des composants.




                                             Nom de la propriété concernée




                                             Valeur de la propriété concernée.




Chaque objet ( composant ) dispose d'un certain nombre de propriétés. Ces propriétés peuvent être initialisées
grâce à l'inspecteur objet ou par programmation.
             sélectionner l'objet en cliquant dessus
             sélectionner la propriété dans l'inspecteur d'objets
             modifier la propriété

Si vous souhaitez que ces propriétés se modifient durant l'application, c'est par programmation que vous devrez
le faire.


Eric.Brasseur@village.uunet.be                                                                                       5
I.E.P.S.C.F. Marche en Famenne                                               Langage orienté gestion ( partie 1)


La feuille de travail.( Unité ) .

Pour la trouver, il faut déplacer la fenêtre de travail et cliquer sur la feuille de travail. A chaque fiche est
attachée une unité. On peut basculer par menu déroulant ou par F12.




Si vous avez plusieurs unités, vous avez plusieurs onglets. Il est possible également de faire apparaître la fiche
du projet ( de l'application ) parmi les onglets. Pour le faire, vous cliquez sur l'icône formée de feuilles
superposées puis sur projet. Vous aurez ceci :




Eric.Brasseur@village.uunet.be                                                                                       6
I.E.P.S.C.F. Marche en Famenne                                                  Langage orienté gestion ( partie 1)


Actuellement, notre application ne contient qu'une fenêtre vide. Le code de l'unité est donc réduit au strict
minimum. On y trouve toutefois les sections suivantes :

             Interface : décrit les notions globales à la fenêtre de travail :

         + uses : déclaration des bibliothèques utilisées
         + type : déclaration des types et des objets ( ici un objet est déclaré : Tform1 de la classe Tform);
                  des variables locales aux objets peuvent y être déclarées; des procédures aussi.
         + var : déclaration des variables globales au programme (ici, déclaration de la fenêtre form1 du type
                   Tform1).

             Implementation : on y trouve les directives de compilation (T.P.C.P.C.) et le développement des
              procédures.


Voici un premier programme qui consiste à enfoncer un bouton pour faire apparaître un message. il faut :

             placer un bouton sur la fenêtre ( je lui ai laissé son nom initial : button1)
             placer un label ( appelé label1 ).
             double-cliquez sur la fenêtre de travail ( en dehors du label et du bouton ) et dans l'unité, vous
              verrez apparaître une procédure FormCreate. Elle sert à passer des informations lors de l'ouverture
              de la fenêtre. Nous l'utiliserons plus tard.
             double-cliquez sur le bouton et une nouvelle procédure apparaît : Tform1.button1click : vous
              ajoutez entre le begin et le end la ligne suivante : label1.caption := 'Vous avez créé votre première
              application'.
             Vous cliquez sur la le raccourci flèche verte pour tester l'application.

Voici dans l'ordre : la fiche, le résultat, l'unité, le projet et l'inspecteur d'objet ( propriétés et




Avant d'enfoncer le bouton.




Eric.Brasseur@village.uunet.be                                                                                        7
I.E.P.S.C.F. Marche en Famenne   Langage orienté gestion ( partie 1)


Après avoir enfoncé le bouton.




                                          Déclaration des
                                          composants du
                                          type Tform1




Eric.Brasseur@village.uunet.be                                         8
I.E.P.S.C.F. Marche en Famenne             Langage orienté gestion ( partie 1)




                                 Texte qui est affiché sur le bouton
                                 ( son nom par défaut )




                                 Nom du bouton




                                                        Procédure liée à l'événement :
                                                        enfoncer le bouton




                                                               Evénements liés à un
                                                               bouton




Eric.Brasseur@village.uunet.be                                                        9
I.E.P.S.C.F. Marche en Famenne                                             Langage orienté gestion ( partie 1)


Le projet.

Vous avez constaté que le projet n'a pas changé en modifiant l'unité. Le projet déclare l'inclusion des fenêtres
qui composent l'application, par l'intermédiaire de l'instruction "uses". Si on a une seule fenêtre, le projet inclut
"unit1", l'unité annexée à la fenêtre "form1", comme le spécifient les lignes de code suivantes :

 Forms,
 Unit1 in 'Unit1.pas' {Form1};
Si on a deux feuilles, on doit inclure ces deux feuilles dans le projet de la façon suivante ( c'est DELPHI qui le
fera pour vous ) :

 Forms,
 Unit1 in 'C:\EXERCICE1\Unit2.pas' {Form2};
Dans ce cas, tout le chemin de l'unité est indiqué.

Ensuite, on trouve les lignes de code nécessaires au bon fonctionnement de l'application :

initialiser; créer les fenêtres;lancer l'exécution.

 Application.Initialize;
 Application.CreateForm(TForm1, Form1);
 Application.Run;
Au cas où l'application compterait plus d'une fenêtre ( j'espère que vous n'en resterez pas à une seule ), cela
deviendrait :

 Application.Initialize;
 Application.CreateForm(TForm1, Form1);
 Application.CreateForm(Tform2, Form2);
 Application.Run;
Quelques conseils :

             il ne faut pas laisser les noms d'origine aux unités, projets, composants des fenêtres. Prenez de
              bonnes habitudes ( même si je ne les respecte pas toujours ). Un exemple : le projet portera le nom
              final de votre application ( par exemple essai1). Pour les composants, il est pratique de commencer
              le nom par l'initiale du composant suivie d'un nom parlant : Bafficher pour le bouton d'affichage…
             il faut sauvegarder régulièrement ses applications; de préférence dans un répertoire propre que vous
              n'utiliserez que pour cette application. Utilisez "sauvegarder tout" ou les disquettes superposées.
             éviter dans la mesure du possible de donner le même nom au composant que ce qu'il affiche à
              l'écran ; de plus, deux composants ne peuvent porter le même nom (sauf …).
             vous constaterez que DELPHI génère toute une série de fichiers : voici ceux qui sont toujours
              générés : ( si le projet s'appelle essai1.dpr et l'unité fenetre1.pas )
         +         essai1.dof : informations sur la version, l'auteur et les options de compilation
         +         essai1.cfg : informations sur la configuration de développement
         +         essai1.res : informations sur la compilation
         +         fenetre1.dfm : description de la fenêtre de travail
         +         fenetre1.pas : le code relatif à la fenêtre de travail
         +         fenetre1.dcu : il s'agit de l'unité compilée
         +         essai1.exe : il s'agit du projet exécutable, que vous pouvez lancer depuis WINDOWS sans que
                   DELPHI ne soit ouvert
             vous trouverez en annexe un schéma de fonctionnement d'une compilation avec exécution




Eric.Brasseur@village.uunet.be                                                                                       10
I.E.P.S.C.F. Marche en Famenne                                           Langage orienté gestion ( partie 1)




Ce schéma est théorique. Il suffit de cliquez sur la flèche verte pour réaliser tout. Sachez que lors d'un mauvais
ou d'un non-fonctionnement d'une application, il existe des outils de correction que vous découvrirez au fur et à
mesure. La connaissance des fichiers générés vous aidera à corriger les erreurs inévitablement commises.

Exercice 201. Vous réalisez le même exercice que précédemment mais en changeant le nom des différents
composants. Le bouton doit porter comme mention : Afficher. Le label doit être vide au départ. La fenêtre doit
porter le titre "Exercice 201".

Exercice 202. Comme exercice précédent, mais vous ajoutez un bouton qui aura comme mention : Effacer et
qui effacera le label affiché. Changement du titre de la fenêtre à chaque nouvel exercice.

Exercice 203. Comme exercice précédent, mais vous ajoutez un bouton pour sortir. Le code est simple :
Application.Terminate.
Exercice 204. Comme exercice précédent, mais le bouton d'affichage devient inutilisable quand on l'a enfoncé et
il rend utilisable le bouton d'effacement. Le bouton d'effacement procède dans le sens contraire.

Exercice 205. Comme exercice précédent, mais le bouton d'affichage s'efface quand on l'enfonce. L'inverse
pour le bouton d'effacement.

Les corrections de ces exercices se trouvent dans le manuel corrigé des exercices.


Eric.Brasseur@village.uunet.be                                                                                   11
I.E.P.S.C.F. Marche en Famenne                                             Langage orienté gestion ( partie 1)


On peut faire varier ce genre d'exercices en utilisant un edit plutôt qu'un label. Attention : l'edit ne possède pas
de propriété appelée caption mais une autre appelée text. Le principe est le même si ce n'est que l'affichage se
fait par défaut sur un fond blanc.

Remarques générales :

            le code de chaque procédure est inscrit entre un begin et un end;
            le nom de la procédure dans l'implémentation est précédé du nom de la fenêtre suivi d'un point
             alors que dans l'interface, ce nom est seul. Ceci s'explique par le fait que dans l'interface, la
             procédure est déclarée à l'intérieur de la déclaration de la fenêtre comme une méthode ( ou
             procédure ) de la fenêtre et il est donc inutile de préciser à qui elle appartient.
            vous constaterez que vous devez juste encoder un minimum de code en langage PASCAL.
             Imaginez ce que doit faire un programmeur qui ne dispose pas d'un RAD.
            le end. final correspond à la fin de l'unité.

Certaines propriétés des composants sont aisément manipulables : fontes couleurs, …
Je vous invite à modifier les exercices que nous venons de voir et d'aller voir dans le fichier .dfm ce qui a pu
changer.

Je ne détaillerai pas toutes les propriétés ni tous les événements liés aux composants. Je vous invite à tester des
variantes. Toutefois, voici une propriété qui rend votre application plus professionnelle : faire apparaître une
info-bulle quand vous survolez un bouton avec la souris. Procédez comme suit :

            Cliquez une fois sur le bouton quitter.
            A côté de la propriété Hint, rédigez le message qui apparaîtra dans cette info-bulle.
            Activez (placez à true) la propriété showhint : c'est elle qui active ou non l'affichage de l'info-bulle.
             La présence du message dans la propriété hint ne suffit pas.

Il ne faut pas exagérer dans l'ajout de messages d'aide, car votre écran serait vite surchargé, ce qui entraînera
l'abandon de leur lecture par les usagers.
Je vous invite de nouveau à lire le fichier .dfm qui a bien changé.

Une variante des boutons traditionnels existe. Pour les découvrir, vous activez l'onglet Supplément de la boîte à
outils et sélectionnez le Bitbtn qui propose des propriétés légèrement différentes.




Jusqu'ici, nous n'avons pas encore abordé la véritable programmation. Vos vœux vont être exaucés.




Eric.Brasseur@village.uunet.be                                                                                      12
I.E.P.S.C.F. Marche en Famenne                                              Langage orienté gestion ( partie 1)


3. LES PREMIERS PAS EN PROGRAMMATION.

La programmation nécessite l'apprentissage de concepts élémentaires :

            connaissances des opérateurs, de leur façon de fonctionner et de leur ordre de priorité
            connaissance des types de variables, de leur capacité, de leurs contraintes
            connaissance des fonctions de conversion des variables
            connaissance des algorithmes de séquences répétitives et de séquences de branchements
             conditionnels
            manipulation des tableaux et des types

Je pourrais étudier ces concepts d'une manière théorique puis vous donner quelques exercices. Toutefois, je
procéderai différemment : je scinderai cette étude en plusieurs étapes.


3.1. Les opérateurs arithmétiques.

Avant tout autre opérateur, parlons de l'opérateur d'affectation : :=
Cet opérateur place la valeur de droite dans la variable de gauche. Ainsi : a := 8 + 14; affectera la valeur 22 à a.
Cet opérateur ne peut donc être utilisé pour comparer deux nombres.

3.1.1. Sur les nombres entiers.

       Opérateur                     Description                          Résultat                  Exemple
+                       Addition                                 entier                  k := i + j;
-                       Soustraction                             entier                  k := i Ŕ j;
- ( unaire )            Inversion du signe ( sauf byte )         entier                  -l
*                       Multiplication                           entier                  k := i * j
/                       Division                                 réel                    k := i/j:
Div                     Division entière                         entier                  k := i div j;
Mod                     Reste de la division entière             entier                  k := i mod j;

y := abs(x) retourne la valeur absolue de x.
y := sqr(x) retourne le carré de x.
p := odd(x) place FALSE dans p si x est un nombre pair et TRUE si x est un nombre impair.

3.1.2. Sur les nombres réels.


       Opérateur                      Description                      Résultat                     Exemple
+                       Addition                                 Réel                    k := i + j;
-                       Soustraction                             Réel                    k := i Ŕ j;
- ( unaire )            Inversion du signe                       Réel                    -l.21
*                       Multiplication                           Réel                    k := i * j
/                       Division                                 Réel                    k := i/j:
Abs                     Valeur absolue                           Réel                    k := abs( i );
Sqr                     Elévation au carré                       Réel                    k:= sqr (j );
Sqrt                    Racine carrée                            Réel                    k := sqrt( i );
Sin                     Sinus ( d'une valeur en radians )        Réel                    k := sin( i ):
Cos                     Cosinus ( d'une valeur en radians )      Réel                    k := cos ( j );
Arctan                  Arc tangente ( en radians )              Réel                    k := arctan ( i );
Ln                      Logarithme népérien                      Réel                    k:= ln ( i );
Exp                     Exponentielle                            Réel                    k := exp ( j );
Trunc                   Tronque la partie décimale               Longint                 Ent := trunc ( i );
Round                   Arrondit à l'entier le plus proche       Longint                 Ent := round (j ):
int                     Tronque la partie décimale mais le       Réel                    k := int(i);
                        résultat est un réel



Eric.Brasseur@village.uunet.be                                                                                    13
I.E.P.S.C.F. Marche en Famenne                                              Langage orienté gestion ( partie 1)


frac                    Renvoie la partie décimale d'un réel      Réel                     k := frac(i);
3.1.3. Les opérateurs de comparaison.

Vous les connaissez déjà : il s'agit de

= ( ne pas confondre avec := )
<=
>=
<
>
<>

La priorité des opérateurs est semblable à celle des mathématiques courantes.


3.2. Les conversions de type de variables.

La représentation des variables en mémoire étant différente suivant le type de la variable ( longueur, cryptage ),
il est important de pouvoir transférer le contenu d'une variable de type 1dans une variable de type 2.




                                              Fonction de conversion
                 variable de                                                            variable de
                   type 2                                                                 type 1




 Exemple : nous avons une chaîne de caractères formée des chiffres 1 et 4 (14 ). Pour pouvoir utiliser ce 14 dans
une opération mathématique, il faut le convertir en nombre (entier ou réel suivant le cas).

Voici quelques fonctions utiles :

heure, date : datetime;
nombre, poscode : integer;
nombreel : double;
cara : char;
asci : byte;


  Nom de la fonction                              Rôle                                          Exemple
inttostr                   Convertit un entier en chaîne                         edit1.text := inttostr(nombre);
strtoint                   Convertit une chaîne en entier                        nombre := strtoint(edit1.text;
floattostr                 Convertit un réel en chaîne                           edit1.text := floattostr(nombreel);
strtofloat                 Convertit une chaîne en réel                          nombreel := strtofloat(edit1.text);
strtotime                  Convertit une chaîne en heure                         heure := strtotime(edit1.text);
strtodate                  Convertit une chaîne en date                          date1 := strtodate(edit1.text);
datetostr                  Convertit une date en chaîne                          edit1.text := datetostr(date1);
val                        Convertit une chaîne en entier ou en réel             val(edit1.text,nombre, poscode);
                           poscode est la position du caractère en erreur
chr                        Convertit un code ASCII en caractère                  cara := chr(asci);

Il en existe d'autres ; nous les détaillerons au fur et à mesure de leur rencontre.


Avant de s'attaquer aux algorithmes de boucles et de branchements conditionnels, nous allons nous exercer avec
les opérateurs et les conversions de type.



Eric.Brasseur@village.uunet.be                                                                                         14
I.E.P.S.C.F. Marche en Famenne                                     Langage orienté gestion ( partie 1)


Voici un exercice simple à réaliser :
1° Préparez la fenêtre qui s'affichera comme telle :




2° Nommez vos boutons bcalcul, bablanc, bquitter et vos edits enombre1, enombre2 et esomme.
3° Déclarez les variables de calcul : n1, n2, somme comme des integer.
4° Voici le code :

unit fenexp16;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 StdCtrls;

type
 Tfen01 = class(TForm)
  Bcalcul: TButton;
  Enombre1: TEdit;
  ENombre2: TEdit;
  Label1: TLabel;
  Label2: TLabel;
  Label3: TLabel;
  Esomme: TEdit;
  Bablanc: TButton;
  Bquitter: TButton;
  procedure BquitterClick(Sender: TObject);
  procedure BcalculClick(Sender: TObject);
  procedure BablancClick(Sender: TObject);
 private
  { Déclarations privées}
                                                                                         déclaration
  n1,n2,somme : integer;
                                                                                         des variables
 public
                                                                                         de travail
  { Déclarations publiques}
 end;

var
 fen01: Tfen01;



Eric.Brasseur@village.uunet.be                                                                           15
I.E.P.S.C.F. Marche en Famenne                                          Langage orienté gestion ( partie 1)



implementation

{$R *.DFM}

procedure Tfen01.BquitterClick(Sender: TObject);
begin
                                                                                       Conversion de chaînes en
 application.terminate;
                                                                                       nombres qui pourront servir au
end;
                                                                                       calcul
procedure Tfen01.BcalculClick(Sender: TObject);
begin
 n1 := strtoint(enombre1.text);                                                        calcul de la somme
 n2 := strtoint(enombre2.text);
 somme := n1 + n2;
 esomme.text := inttostr(somme);
end;                                                                                   Conversion de la somme en
                                                                                       chaîne qui pourra être affichée.
procedure Tfen01.BablancClick(Sender: TObject);
begin
  n1 := 0;
  n2 := 0;
  somme := 0;
  enombre1.text := '';                                                                 Mise à blanc de mes zones edit
  enombre2.Text := '';
  esomme.text := '';
end;

end.

Testez le même exercice avec val au lieu de strtoint.
Vous avez constaté qu'une erreur est vite commise. Si vous entrez une valeur incorrecte, la conversion provoque
une erreur à l'exécution. Votre programme s'arrête vilainement. Il est possible de limiter ces erreurs : voici une
possibilité que je vous demande d'accepter telle quelle pour le moment. Cette méthode est un peu fastidieuse
mais fonctionne très bien si le programme est lancé directement depuis WINDOWS.

procedure Tfen01.BcalculClick(Sender: TObject);
begin
  try                                                                                  On essaye la conversion
   n1 := strtoint(enombre1.text);
  except
   on E: Econverterror do                                                              Si une erreur de
     begin                                                                             conversion se déclenche,
       showmessage('Du numérique S.V.P.');                                             on met 0 dans n1 et dans
       n1 := 0;                                                                        la zone d'affichage
       enombre1.text := inttostr(0);
     end;
  end;
  try
   n2 := strtoint(enombre2.text);
  except
   on E: Econverterror do
     begin                                                                             Affichage d'un message
       showmessage('Du numérique S.V.P.');                                             d'erreur dans une petite
       n2 := 0;                                                                        fenêtre
       enombre2.text := inttostr(0);
     end;
  end;
 somme := n1 + n2;
 esomme.text := inttostr(somme);



Eric.Brasseur@village.uunet.be                                                                                    16
I.E.P.S.C.F. Marche en Famenne                                            Langage orienté gestion ( partie 1)


end;
Nous verrons plus tard qu'il est possible d'empêcher la saisie d'autres caractères que des chiffres. Voici des
exercices du même genre :

exercice 301 : vous entrez un montant hors TVA puis un taux de TVA et vous calculez le montant TVAC.

exercice 302 : vous entrez un nombre de kilomètres parcourus puis un nombre de litres consommés et vous
affichez la consommation par 100 kms.

exercice 303 : résolution d'une équation du type ax + b Ŕ c = 0 avec une présentation soignée.
Si je vous dis que l'ordre de priorité des opérations est le suivant :

    1.     ()
    2.     Ŕ (opposé)
    3.     not
    4.     *, /, div, mod, and, or
    5.     +, - ( soustraction)
    6.     =, <, >, <=, >=, <> ( opérateurs relationnels)

exercice 304 : écrivez l'exercice qui me permettra d'afficher le résultat des opérations suivantes :
X := A + B * C;
X := (A + B) * C;
X := A * B + C;
X := A * (B + C);
X := A + C / B;
X := (A + C) / B;
X:=C / A + B;
X:=C / (A + B);
Vous prévoyez une zone de saisie pour les variables entières A, B, C, et une zone d'affichage pour le réel X.
Testez avec les valeurs 1, 2 et 3.

exercice 305 : jeu de la machine à écrire. Voici un programme qui simule l'utilisation d'une machine à écrire
simple :




Cet exercice est évidemment très long à encoder. En avançant, nous allons découvrir des méthodes réductrices
de code. On constate que pour ajouter un caractère à la fin d'un string, il suffit d'utiliser le signe '+'. On dira
qu'on a procédé à la concaténation. Il nous faudra trouver un système pour simuler le retour arrière,…



Eric.Brasseur@village.uunet.be                                                                                    17
I.E.P.S.C.F. Marche en Famenne                                           Langage orienté gestion ( partie 1)


Ces exercices nous ont révélé quelques lacunes :

             Que faire si un utilisateur donne un nombre de kilomètres parcourus égal à 0 ( l'exercice n° 302 ) ?
             Que faire si la valeur a est nulle dans l'exercice n° 303 ?

Il faut pouvoir tester si les valeurs encodées sont bonnes ou pas.

3.3. Les branchements conditionnels ( ou les instructions de test ).

Nous allons travailler sur le test : si… alors… sinon … (if…then…else…)

Partons d'un programme qui lit un résultat sur 100 et un prénom et qui écrira une phrase du genre : 'Bonjour
prénom, vous avez obtenu points sur 100, où prénom et points correspondent valeurs entrées.
 .




Voici le code du programme.

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 StdCtrls, Buttons;

type
 Ttest1 = class(TForm)
  Lmontre: TLabel;
  Eprenom: TEdit;
  Epoint: TEdit;
  Lprenom: TLabel;
  Lpoint: TLabel;
  baffiche: TButton;
  Bablanc: TButton;


Eric.Brasseur@village.uunet.be                                                                                   18
I.E.P.S.C.F. Marche en Famenne                                       Langage orienté gestion ( partie 1)


  BitBtn1: TBitBtn;
  procedure bafficheClick(Sender: TObject);
  procedure BablancClick(Sender: TObject);
  procedure BitBtn1Click(Sender: TObject);
 private                                                           bitbouton
  { Déclarations privées}
 public
  { Déclarations publiques}
 end;

var
 test1: Ttest1;

implementation

{$R *.DFM}

procedure Ttest1.bafficheClick(Sender: TObject);
begin
  lmontre.caption := 'Bonjour ' + Eprenom.text + ' , vous avez obtenu ' + Epoint.text + ' points.';
end;

procedure Ttest1.BablancClick(Sender: TObject);
begin
  lmontre.caption := ' ';
  epoint.text := '';
  eprenom.text := '';
end;

procedure Ttest1.BitBtn1Click(Sender: TObject);
begin
 application.terminate;
end;

end.

Voici le schéma logique :




                                       Saisie du prénom et des
                                                points




                                              bouton




                                        Affichage de la phrase




Eric.Brasseur@village.uunet.be                                                                             19
I.E.P.S.C.F. Marche en Famenne                                              Langage orienté gestion ( partie 1)


Imaginons maintenant de remplacer l'affichage des points par une mention 'vous avez réussi.' ou 'vous êtes en
échec'.

En français : si points >= 50, alors affichage 'Vous avez réussi.' sinon affichage 'Vous êtes en échec.'.

La procédure bafficheClick deviendra :
                                                                                 Conversion en entier
procedure Ttest1.bafficheClick(Sender: TObject);
begin
 if strtoint(epoint.text) >= 50 then
    begin
     lmontre.caption := 'Bonjour ' + Eprenom.text + ' , vous avez réussi.';                 Bloc begin…end
    end
 else
    begin
     lmontre.caption := 'Bonjour ' + Eprenom.text + ' , vous êtes en échec.';                 Bloc begin…end;
    end;
end;

Vous remarquerez les points qui suivent :

            pas de ; derrière les begin, ni derrière le then et le else
            pas de ; avant le else
            quand le bloc begin…end du then ou du else ne contient qu'une seule ligne, on peut s'abstenir
             d'écrire le begin et le end. Il est équivalent d'écrire :

procedure Ttest1.bafficheClick(Sender: TObject);
begin
 if strtoint(epoint.text) >= 50 then
    lmontre.caption := 'Bonjour ' + Eprenom.text + ' , vous avez réussi.'                     Pas de ;
 else
    lmontre.caption := 'Bonjour ' + Eprenom.text + ' , vous êtes en échec.';                  Il y a un ;
end;

Comme ci-dessus, pas de ; avant le else alors qu'il y en a un plus loin. Le schéma logique devient :




                                          Saisie du prénom et des points




                                                    bouton



                                    non                                    oui
                                                     >= 50


            Affichage échec                                                        Affichage réussite




Eric.Brasseur@village.uunet.be                                                                                    20
I.E.P.S.C.F. Marche en Famenne                                             Langage orienté gestion ( partie 1)


Il existe un test simplifié du si. Voici un exemple :

Nous revenons au premier cas. Nous afficherons toujours les points, mais si les résultats sont inférieurs à 50,
une boîte à message apparaît avec la mention : Dommage, vous êtes en échec. Voici la procédure :

procedure Ttest1.bafficheClick(Sender: TObject);
begin
  if strtoint(epoint.text) < 50 then
     begin
       showmessage('Vous êtes en échec!!!!!');
     end;
  lmontre.caption := 'Bonjour ' + Eprenom.text + ' , vous avez obtenu ' + Epoint.text + ' points.';
end;


Vous remarquerez l'absence de else. On teste le résultat et on n'affiche que si les points sont mauvais. En
schéma logique, ceci donne :




                                     Saisie du prénom et des points




                                               bouton




                                                 < 50


                                                                                     Affichage échec




Exercice 306 : même exercice que le 302 mais avec test du nombre de kilomètres différent de 0.

Exercice 307 : même exercice que le 303 mais le coefficient a doit être non nul.
Il est toujours possible de faire des tests à l'intérieur d'un bloc begin…end. Il s'agit de test imbriqués. Le
chevauchement des tests est impossible. Il faut savoir qu'un end ferme toujours le dernier begin ouvert.

Exercice 308 : Rédigez le programme qui dira Bonjour Madame à une personne du sexe féminin et Bonjour
Monsieur à une personne du sexe masculin. Vous devez tester également la possibilité qu'on se soit trompé en
tapant une autre lettre que F ou f ou M ou m. Rédigez le schéma logique de ce programme.


Eric.Brasseur@village.uunet.be                                                                                    21
I.E.P.S.C.F. Marche en Famenne                                             Langage orienté gestion ( partie 1)


3.4. La structure de choix multiples.

Imaginons la situation suivante : vous êtes secrétaire de l'école et vous devez sortir les attestations de réussite
des élèves. Un élève a la mention :
            échec si son résultat est inférieur à 60
            satisfaction si son résultat est supérieur ou égal à 60 mais est inférieur à 70
            distinction si son résultat est supérieur ou égal à 70 mais est inférieur à 80
            grande distinction si son résultat est supérieur ou égal à 80 mais est inférieur à 90
            la plus grande distinction si son résultat est supérieur ou égal à 90

Evidemment, cet exercice peut être résolu en utilisant des if successifs ; je vous fournis par ailleurs la solution.
Toutefois, le langage PASCAL dispose d'une structure spécifique : le case…of…

procedure Ttest1.bafficheClick(Sender: TObject);
begin
  if strtoint(epoint.text) < 60 then
     begin
       showmessage('Vous êtes en échec!!!!!');
     end
  else
     begin
       if strtoint(epoint.text) < 70 then
          begin
            showmessage('Vous avez réussi avec satisfaction');
          end
       else
          begin
            if strtoint(epoint.text) < 80 then
               begin
                 showmessage('Vous avez obtenu une distinction');
               end
            else
                begin
                  if strtoint(epoint.text) < 90 then
                     begin
                       showmessage('Vous avez obtenu une grande distinction');
                     end
                  else
                     begin
                       if strtoint(epoint.text) < 101 then
                          begin
                            showmessage('Vous avez obtenu la plus grande distinction');
                          end
                       else
                          begin
                            showmessage('Mauvais encodage');
                          end;
                     end;
                end;
          end;
     end;
  lmontre.caption := 'Bonjour ' + Eprenom.text + ' , vous avez obtenu '
                 + Epoint.text + ' points.';
end;

Dans une telle structure, il est important d'indenter ( reculer les blocs vers la droite ). J'ai intentionnellement
marqué les blocs avec des traits verticaux. Prenez l'habitude de le faire sur votre brouillon : cela vous aidera à ne
pas oublier un end.

Voici le même exercice en utilisant la structure à choix multiples :


Eric.Brasseur@village.uunet.be                                                                                         22
I.E.P.S.C.F. Marche en Famenne                                             Langage orienté gestion ( partie 1)



procedure Ttest1.bafficheClick(Sender: TObject);
begin
  case strtoint(epoint.text) of
    0..59 : showmessage('Vous êtes en échec');
    60..69 : showmessage('Vous avez réussi avec satisfaction');
    70..79 : showmessage('Vous avez obtenu une distinction');
    80..89 : showmessage('Vous avez obtenu une grande distinction');
    90..100 : showmessage('Vous avez obtenu la plus grande distinction');
    else      showmessage('Mauvais encodage');
  end;
  lmontre.caption := 'Bonjour ' + Eprenom.text + ' , vous avez obtenu '
             + Epoint.text + ' points.';
end;

Evidemment, j'ai un peu triché car si j'avais travaillé comme plus haut, j'aurais écrit :

procedure Ttest1.bafficheClick(Sender: TObject);
begin
  case strtoint(epoint.text) of
    0..59 : begin
                  showmessage('Vous êtes en échec');
              end;
    60..69 : begin
                 showmessage('Vous avez réussi avec satisfaction');
              end;
    70..79 : begin
                 showmessage('Vous avez obtenu une distinction');
              end;
    80..89 : begin;
                 showmessage('Vous avez obtenu une grande distinction');
              end;
    90..100 : begin
                 showmessage('Vous avez obtenu la plus grande distinction');
              end;
    else      begin
                 showmessage('Mauvais encodage');
             end;
  end;
  lmontre.caption := 'Bonjour ' + Eprenom.text + ' , vous avez obtenu '
             + Epoint.text + ' points.';
end;



Ici, la lecture se trouve fort simplifiée si on supprime les begin…end quand il n'y a qu'une seule ligne dans le
bloc de code; ce n'est pas toujours le cas avec les if imbriqués.

Toutefois, cette structure présente des inconvénients :

            impossible de lancer des tests sur des variables
            impossible de tester une chaîne
            impossible de lancer un test sur une expression structurée ( contenant des and, or not )
            impossible de lancer des tests sur des expressions de comparaison (<, >, et leurs dérivés)

Je ne vous donnerai pas d'exercice sur cette structure. nous la rencontrerons durant l'annéedans des exercices
plus complets.




Eric.Brasseur@village.uunet.be                                                                                     23
I.E.P.S.C.F. Marche en Famenne                                            Langage orienté gestion ( partie 1)


3.5. Les structures répétitives.

Il est souvent utile de faire exécuter plusieurs fois les mêmes instructions. Le langage PASCAL a prévu trois
structures qui permettent les répétitions d'instructions.

3.5.1. Le nombre d'itérations est déterminé ( soit par le programmeur, soit durant l'utilisation du programme ).

Je désire imprimer 10 fois la phrase 'Impression de la ligne' dans un label avec saut à la ligne à chaque passage.

procedure TForm1.Button1Click(Sender: TObject);
var
 i : integer;
begin
  for i := 1 to 10 do
    begin
      label1.Caption := label1.caption +'Impression de la ligne' + #13;
    end;
end;


                                                                           Code ascii du retour chariot


La boucle for permet d'effectuer le nombre de passages qui correspond au nombre de départ jusqu'au nombre
d'arrivée. L'itération est toujours de 1 ( la possibilité d'utiliser un pas différent n'existe pas en PASCAL). Vous
pouvez toutefois décrémenter ( descendre par pas de 1 ) comme suit

for i := 15 downto 4 do

Comme pour le if, si le bloc de code ne contient qu'une seule instruction, vous pouvez vous passer du begin et du
end. Ceci deviendrait :

procedure TForm1.Button1Click(Sender: TObject);
var
 i : integer;
begin
  for i := 1 to 10 do label1.Caption := label1.caption + 'Impression de la ligne' + #13;
end;


Imaginons un exercice où vous ajoutez un edit qui permet à l'utilisateur d'entrer lui-même la limite supérieure.

procedure TForm1.Button1Click(Sender: TObject);
var
 i : integer;
begin
  for i := 1 to strtoint(edit1.text) do label1.Caption := label1.caption + 'Impression de la ligne' + #13;
end;

                        La limite doit être un entier



Vous remarquerez que j'ai déclaré l'entier i à l'intérieur de la procédure. On dira que i est une variable locale de
la procédure. La valeur contenue dans le i ne pourra pas être utilisée autre part que dans cette procédure ; mieux-
même, les autres procédures ne connaissent pas ce i. A la rigueur, elles pourraient utiliser une variable i qui leur
serait locale et qui ne perturberait pas mon programme.




Eric.Brasseur@village.uunet.be                                                                                     24
I.E.P.S.C.F. Marche en Famenne                                            Langage orienté gestion ( partie 1)


Voici le schéma logique de cet exercice :




                                               Saisie du nombre




                                                     bouton


                                                    i=1


                                                                                  oui           écrire la ligne
                                               i <=nombre ?                                            +
                                                                                               incrémentation
                                                                                                 automatique

                                              non



L'instruction de boucle for… to (ou downto)… do fixe le point de départ du nombre à comparer et la fin du bloc
d'instruction procède automatiquement à l'incrémentation ou à la (décrémentation).

3.5.2. La boucle tant que…fait…

Voici une boucle qui est toujours utilisable, que le nombre d'itérations soit connu ou qu'il résulte d'une situation
interne au programme ou à son utilisation. Voici comment l'utiliser dans la même situation que ci-dessus :


procedure TForm1.Button1Click(Sender: TObject);
var
  i : integer;
begin
  i := 1;                                                                         Initialisation de la variable de test
  while (i <= strtoint(edit2.text)) do
    begin
       label1.caption := label1.caption + 'Impression de la ligne' + #13;
       i := i + 1;                                                                Incrémentation de la variable de test
    end;
end;


Le résultat est équivalent à celui de la boucle for… toutefois, voici quelques différences :

            avec la boucle while, il faut initialiser soi-même la variable de test, pas avec la boucle for
            avec la boucle while, il faut incrémenter soi-même la variable de test dans le bloc des instructions
             exécutées durant le passage dans la boucle, pas avec la boucle for
            le pas d'incrémentation de la boucle while peut être choisi par le programmeur ou même par
             l'utilisateur; avec la boucle for, c'est toujours 1 ou Ŕ1
            la boucle while…do … est toujours utilisable, pas la boucle for…
            on utilise la boucle for quand on a un nombre de fois à exécuter la boucle. Parfois, le nombre de
             passages dans la boucle n'est pas connu ( ex : jeu de l'encadrement ).
            la boucle s'exécute tant que la condition est vraie.




Eric.Brasseur@village.uunet.be                                                                                      25
I.E.P.S.C.F. Marche en Famenne                                           Langage orienté gestion ( partie 1)


Voici le schéma logique :




                                             Saisie du nombre




                                                   bouton




                                            initialisation de i




                                                                        oui
                                                                                      Impression du message
                                            i <=nombre ?                              Incrémentation de i


                                             non



Il est parfaitement possible qu'on ne passe jamais dans la boucle ( si i est directement > que le nombre choisi)
(ceci est aussi vrai avec la boucle for).


3.5.3. La boucle répète…jusqu'à ce que…

Cette structure de boucle fonctionne jusqu'au moment où vous répondez à la condition. C'est à dire qu'elle
fonctionne tant que la condition est fausse. Remplacez dans l'exercice la procédure du bouton par celle-ci :

procedure TForm1.Button1Click(Sender: TObject);
var
  i : integer;
begin
  i := 1;                                                                             Initialisation de i
   repeat
       label1.caption := label1.caption + 'Impression de la ligne' + #13;
       i := i + 1;                                                                    Incrémentation de i
   until (i > strtoint(edit2.text));
end;




   Attention à la comparaison : il faut
   donner la condition de fin et non la
   condition de validité.




Eric.Brasseur@village.uunet.be                                                                                     26
I.E.P.S.C.F. Marche en Famenne                                           Langage orienté gestion ( partie 1)


Voici le schéma logique :




                                             Saisie du nombre




                                                bouton




                                            initialisation de i




                                       Impression du message
                                       Incrémentation de i




                                                                        non
                                               i > nombre ?



                                                        oui




Dans un bloc repeat …until, on passe toujours au moins une fois dans le bloc de la boucle car le test a lieu après
le passage.

Exercice 309. En choisissant la bonne structure, réalisez le programme qui consiste à faire choisir un nombre
caché à l'ordinateur (fonctions random et randomize ) et à demander à l'utilisateur d'entrer un nombre. S'il est
trop petit ou trop grand, l'ordinateur le signale. La recherche doit avoir lieu jusqu'au moment où le nombre est
trouvé.
Exercice 310. Ecrivez le programme qui permet à l'utilisateur d'entrer trois nombres. Affichez le plus grand.
Exercice 311. Même exercice mais en affichant les 3 nombres dans l'ordre croissant.
Exercice 312. Recherche du factoriel d'un nombre naturel encodé par l'utilisateur. (factoriel 4 = 4 * 3 * 2 * 1).
Exercice 313. Recherche de tous les nombres premiers compris entre 1 et un nombre saisi par l'utilisateur.
Exercice 314. Ecrivez le programme qui calcule les racines réelles d'une équation du type ax²+bx+c=0.
Exercice 315. Affichez le tableau des produits pour les nombres variant entre 1 et n ( n est un nombre entier
entré au clavier).
Exercice 316. Calculez la somme et le produit des nombres entrés au clavier jusqu'à l'introduction de 0.
Exercice 317. Ecrivez la chaîne formée par les caractères entrés au clavier jusqu'à l'introduction de 0.




Eric.Brasseur@village.uunet.be                                                                                  27
I.E.P.S.C.F. Marche en Famenne                                           Langage orienté gestion ( partie 1)


3.6. La manipulation des tableaux.

Un tableau est un ensemble ordonné de variables de même type. Cet ensemble de variables ne porte qu'un seul
nom et chaque élément est accessible grâce à sa position.
Attention : il s'agit bien d'une réservation d'un emplacement en mémoire centrale. Cet emplacement occupe la
place d'un élément du tableau multipliée par le nombre d'éléments. il ne s'agit donc pas d'une écriture sur un
support magnétique ( fichier ).

Il est habituel de représenter un tableau comme une suite de variables : exemple :

var
  tabentier : array[1..10] of integer;




   élément 1                                élément 6

   tabentier[1]                             tabentier[6]


Chaque élément compte 4 bytes; on a donc réservé 40 bytes dans la mémoire centrale. Chaque élément se
comporte comme n'importe quelle variable entière.
Pour le remplir, je peux écrire :

tabentier[1] := 43;
tabentier[6] := -12;
tabentier[4] := tabentier[1] + tabentier[6];

Il est possible de créer des tableaux à plusieurs dimensions. Toutefois, je vous invite à ne pas dépasser le tableau
à 2 dimensions car vous aurez difficile de vous représenter un tableau à plus de deux dimensions.

var
 tabcaract : array[1..6,1..4] of char;




                                                                                     élément ligne 2 colonne 6

                                                                                     tabcaract[2,6]




            élément ligne 1 colonne 3

            tabcaract[1,3]


Vous pouvez représenter votre tableau en colonnes lignes au lieu de lignes colonnes, mais il faut rester rigoureux
avec votre façon de travailler. Ce n'est jamais qu'une représentation virtuelle. La mémoire est organisée
différemment.
En quoi les tableaux sont-ils utiles ? Partons d'un exemple : vous souhaitez inscrire les résultats des élèves pour
calculer leur moyenne. Prenons simplement 2 élèves avec 3 branches. Voici un code sans tableau.



Eric.Brasseur@village.uunet.be                                                                                   28
I.E.P.S.C.F. Marche en Famenne                                   Langage orienté gestion ( partie 1)


unit Unit1;
interface
uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 StdCtrls, Grids;
type
 TFexercice = class(TForm)
   Bquitter: TButton;
   Bdemarre: TButton;
   EA: TEdit;
   Label1: TLabel;
   EB: TEdit;
   Label2: TLabel;
   EC: TEdit;
   ED: TEdit;
   EE: TEdit;
   EF: TEdit;
   label3: TLabel;
   Label4: TLabel;
   Label5: TLabel;
   grille: TStringGrid;
   procedure BquitterClick(Sender: TObject);
   procedure BdemarreClick(Sender: TObject);
 private
 public
 end;
var
 Fexercice: TFexercice;
implementation
{$R *.DFM}
procedure TFexercice.BdemarreClick(Sender: TObject);
var
  el1br1, el1br2,el1br3,el2br1,el2br2,el2br3 : integer;
  moyenne1, moyenne2 : real;
begin
  el1br1 := strtoint(EA.text);
  el1br2 := strtoint(EB.text);
  el1br3 := strtoint(EC.text);
  el2br1 := strtoint(ED.text);
  el2br2 := strtoint(EE.text);
  el2br3 := strtoint(EF.text);
  moyenne1 := (el1br1 + el1br2 + el1br3) / 3;
  moyenne2 := (el2br1 + el2br2 + el2br3) / 3;
  grille.visible := true;
  grille.cells[1,0] := 'Branche 1';
  grille.cells[2,0] := 'Branche 2';
  grille.cells[3,0] := 'Branche 3';
  grille.cells[4,0] := 'Moyenne';
  grille.cells[0,1] := 'Elève 1';
  grille.cells[0,2] := 'Eleve 2';
  grille.cells[1,1] := EA.text;
  grille.cells[2,1] := EB.text;
  grille.cells[3,1] := EC.text;
  grille.cells[4,1] := floattostr(moyenne1);
  grille.cells[1,2] := ED.text;
  grille.cells[2,2] := EE.text;
  grille.cells[3,2] := EF.text;
  grille.cells[4,2] := floattostr(moyenne2);
end;




Eric.Brasseur@village.uunet.be                                                                         29
I.E.P.S.C.F. Marche en Famenne                                       Langage orienté gestion ( partie 1)


procedure TFexercice.BquitterClick(Sender: TObject);
begin
 application.terminate;
end;

end.




Voici maintenant le même exercice mais en utilisant un tableau qui me permettra de raccourcir mon code. De
plus, j'ai implémenté la saisie des notes dans un inputbox.


unit Unit1;
interface
uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 StdCtrls, Grids;
type
 TFexercice = class(TForm)
   Bquitter: TButton;
   Bdemarre: TButton;
   grille: TStringGrid;
   procedure BquitterClick(Sender: TObject);
   procedure BdemarreClick(Sender: TObject);




Eric.Brasseur@village.uunet.be                                                                               30
I.E.P.S.C.F. Marche en Famenne                                            Langage orienté gestion ( partie 1)


 private
  { Déclarations privées}
 public
   { Déclarations publiques}
 end;

var
 Fexercice: TFexercice;
 notes : array[1..2,1..3] of integer;

implementation

{$R *.DFM}

procedure TFexercice.BquitterClick(Sender: TObject);
begin
 application.terminate;
end;

procedure TFexercice.BdemarreClick(Sender: TObject);
var
  i, j, somme : integer;
  moyenne : real;
begin
  for i := 1 to 3 do grille.cells[i,0] := 'Branche ' + inttostr(i);
  grille.cells[4,0] := 'Moyennes';
  for i := 1 to 2 do grille.cells[0,i] := 'Elève ' + inttostr(i);
  for i := 1 to 2 do
     begin
        somme := 0;
        for j := 1 to 3 do
          begin
            notes[i,j] := strtoint(inputbox( 'Saisie', 'Entrez les points de la branche ' + inttostr(j) +
                                               ' de l''élève ' + inttostr(i),'0'));
            somme := somme + notes[i,j];
            grille.cells[j,i] := inttostr(notes[i,j]);
          end;
        moyenne := somme / 3;
        grille.cells[4,i] := floattostr(moyenne);
     end;
  grille.visible := true;
end;
end.

Exercice 318.        Recommencez le même programme, mais en permettant à l'utilisateur de choisir au départ
le nombre d'élèves et le nombre de branches (grâce à des inputbox). Ne dépassez pas 20 branches et 30 élèves.
Exercice 319.         Recommencez le même exercice, mais en saisissant au préalable les noms des branches et
des élèves en les faisant apparaître dans la grille et le inputbox.
Exercice 320. Dessinez le triangle de Pascal pour un nombre choisi par l'utilisateur.
Exercice 321. Calculez l'élément n de la suite de Fibonacci et affichez les vérifications.
Exercice 322. Affichez dans une matrice MC la somme des matrices MA et MB. (taille indéterminée ).
Exercice 323. Produit d'une matrice par un nombre.
Exercice 324. Produit de 2 matrices.
La représentation que nous avons des tableaux est régie généralement par l'ordre ligne-colonne. Toutefois,
lorsqu'on parle des Tstinggrid, l'ordre est colonne-ligne. De plus, la première colonne et la première ligne
portent l'indice 0 alors que nous travaillons le plus souvent dans les tableaux avec comme premier indice 1.



Eric.Brasseur@village.uunet.be                                                                                  31
I.E.P.S.C.F. Marche en Famenne                                            Langage orienté gestion ( partie 1)


4. QUELQUES COMPOSANTS DE DELPHI.
Avant de s'attaquer à quelques grands algorithmes ( tris, fusions, recherche) et aux fichiers, nous allons étudier
quelques composants qui améliorent et professionnalisent nos applications.

4.1. Les groupbox et les radiobutton.

Un groupbox est un cadre ( en anglais frame ) qui permet de regrouper d'autres composants. Il existe plusieurs
cadres différents : le panel et le radiogroup. Si vous déplacez un radiogroup, vous déplacez également tous ses
composants, ce qui vous aidera beaucoup lors de la constitution de vos applications. Il faut d'abord installer le
cadre puis ensuite ses composants. Vous avez la possibilité de donner un titre à votre cadre.

Un radiobutton est un bouton rond qui peut contenir un point noir au centre s'il a été activé (checked). Dans un
groupe de radiobuttons, un seul peut être activé : quand vous cliquez sur un des radiobuttons, tous les autres du
groupe sont automatiquement désactivés. Ex : marié, célibataire, divorcé, veuf.

Voici un exemple à réaliser : deux radiobuttons permettent de déterminer le sexe. Si c'est féminin, affichage de
'Bonjour, Madame' autrement, 'Bonjour, Monsieur'.

unit Unit1;
interface
uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Buttons;
type
 TForm1 = class(TForm)
   Bquitte: TBitBtn;
   GBSEXE: TGroupBox;
   RBMALE: TRadioButton;
   RBFEMALE: TRadioButton;
   procedure RBFEMALEClick(Sender: TObject);
   procedure RBMALEClick(Sender: TObject);
   procedure BquitteClick(Sender: TObject);
 private
 public
 end;

var
 Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.RBFEMALEClick(Sender: TObject);
begin
  showmessage('Bonjour Madame');
end;

procedure TForm1.RBMALEClick(Sender: TObject);
begin
 showmessage('Bonjour Monsieur');
end;

procedure TForm1.BquitteClick(Sender: TObject);
begin
 application.terminate;
end;

end.

Exercice 401 :        Même exercice mais vous devez dire bonjour ou bonsoir si on est le matin ou le soir.
Exercice 402 :        Même exercice mais vous devez utiliser Madame ou Mademoiselle ou Monsieur.



Eric.Brasseur@village.uunet.be                                                                                       32
I.E.P.S.C.F. Marche en Famenne                                           Langage orienté gestion ( partie 1)


4.2. Les cases à cocher.

Les cases à cocher ( checkbox ) fonctionnent de la même façon que les radiobuttons mais plusieurs options
peuvent être cochées simultanément.

Exercice 403 : Vous saisissez le nom et le sexe d'un individu et vous lui demandez de cocher parmi 12
goûts personnels. Ensuite, vous affichez une phrase du genre : Madame Dupont, vous aimez la musique, la
lecture, le football.




4.3. Les ComboBox ( Boîtes à options).

La boîte à options permet le choix d'un élément parmi plusieurs dans une liste. Les éléments sont préinstallés
par le programmeur mais il est possible d'en ajouter lors de l'utilisation. Nous partons d'une situation simple :
vous travaillez dans un secrétariat de promotion sociale et vous devez renseigner les élèves sur les cours suivis.
Voici un tableau des renseignements à fournir :
Classe             Diplôme              Heures/semaines Droit                   Cotisation          Niveau
                                                           d'inscription        amicale
INFO 1             NON                  13                 5500                 1000                ESEC
INFO2              NON                  12.5               5500                 1000                ESEC
INFO 3             OUI                  12                 5500                 1000                ESEC
COMPTA 1           NON                  12                 5500                 1000                ESEC
COMPTA 2           NON                  11                 5500                 1000                ESEC
COMPTA 3           OUI                  7                  4500                 1000                ESEC
ŒNOLOGIE           OUI                  4                  5500                 500                 ESS
GUIDE 1            NON                  6                  4000                 500                 ESS
GUIDE 2            OUI                  6                  4000                 500                 ESS




Eric.Brasseur@village.uunet.be                                                                                   33
I.E.P.S.C.F. Marche en Famenne                                           Langage orienté gestion ( partie 1)


Ici, ces données seront encodées directement au moment de la programmation. Dans un programme réel, toutes
ces données sont encodées par une personne autorisée, les modifications sont apportées lorsqu'il le faut et tout est
conservé sur le disque ( dans un fichier ) pour les utilisations ultérieures.
Voici l'écran à obtenir.




unit Unit1;
interface
uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 StdCtrls, Buttons;
type
 description = record
    classe : string[20];
    diplome : string[3];                Déclaration du
    heures : string[4];                 type record
    inscription : string[5];            (enregistrement)
    amicale : string[5];
    niveau : string[5];
 end;
 TForm1 = class(TForm)
   Bquitte: TBitBtn;
   CBchoix: TComboBox;
   Label1: TLabel;
   Label2: TLabel;
   ldiplome: TLabel;
   lheures: TLabel;
   Linscription: TLabel;
   Label5: TLabel;
   Label6: TLabel;
   Label7: TLabel;
   Label8: TLabel;
   Lamicale: TLabel;
   Lniveau: TLabel;
   procedure BquitteClick(Sender: TObject);
   procedure FormCreate(Sender: TObject);
   procedure CBchoixChange(Sender: TObject);
 private
 public
 end;
var
 Form1: TForm1;
                                                         déclaration d'un tableau
 descrip : array[0..8] of description;
                                                         dont les éléments sont du
implementation
                                                         type description
{$R *.DFM}
procedure TForm1.BquitteClick(Sender: TObject);


Eric.Brasseur@village.uunet.be                                                                                   34
I.E.P.S.C.F. Marche en Famenne                   Langage orienté gestion ( partie 1)


begin
  application.terminate;
end;
procedure TForm1.FormCreate(Sender: TObject);
var i : integer;
begin
  descrip[0].classe := 'INFO 1';
  descrip[0].diplome := 'NON';
  descrip[0].heures := '13';
  descrip[0].inscription := '5500';
  descrip[0].amicale := '1000';
  descrip[0].niveau := 'ESEC';
  descrip[1].classe := 'INFO 2';
  descrip[1].diplome := 'NON';
  descrip[1].heures := '12.5';
  descrip[1].inscription := '5500';
  descrip[1].amicale := '1000';
  descrip[1].niveau := 'ESEC';
  descrip[2].classe := 'INFO 3';
  descrip[2].diplome := 'OUI';
  descrip[2].heures := '12';
  descrip[2].inscription := '5500';
  descrip[2].amicale := '1000';
  descrip[2].niveau := 'ESEC';
  descrip[3].classe := 'COMPTA 1';
  descrip[3].diplome := 'NON';
  descrip[3].heures := '12';
  descrip[3].inscription := '5500';
  descrip[3].amicale := '1000';
  descrip[3].niveau := 'ESEC';                  Je remplis mon tableau avec les valeurs
  descrip[4].classe := 'COMPTA 2';              correspondantes.
  descrip[4].diplome := 'NON';                  Attention je commence à 0 car le
  descrip[4].heures := '11';                    premier item d'un combo est d'indice 0.
  descrip[4].inscription := '5500';
  descrip[4].amicale := '1000';
  descrip[4].niveau := 'ESEC';
  descrip[5].classe := 'COMPTA 3';
  descrip[5].diplome := 'OUI';
  descrip[5].heures := '7';
  descrip[5].inscription := '4500';
  descrip[5].amicale := '1000';
  descrip[5].niveau := 'ESEC';
  descrip[6].classe := 'OENOLOGIE';               Je remplis mon combo
  descrip[6].diplome := 'OUI';                    avec le premier élément
  descrip[6].heures := '4';                       du tableau
  descrip[6].inscription := '5500';
  descrip[6].amicale := '500';
  descrip[6].niveau := 'ESS';
  descrip[7].classe := 'GUIDE 1';
  descrip[7].diplome := 'NON';
  descrip[7].heures := '6';
  descrip[7].inscription := '4000';
  descrip[7].amicale := '500';
  descrip[7].niveau := 'ESS';
  descrip[8].classe := 'GUIDE 2';
  descrip[8].diplome := 'OUI';
  descrip[8].heures := '6';                                  Je positionne mon combo
  descrip[8].inscription := '4000';                          sur le premier élément pour
  descrip[8].amicale := '500';                               le lancement
  descrip[8].niveau := 'ESS';



Eric.Brasseur@village.uunet.be                                                            35
I.E.P.S.C.F. Marche en Famenne                                               Langage orienté gestion ( partie 1)


  for i := 0 to 8 do CBchoix.items.add(descrip[i].classe);
  cbchoix.ItemIndex := 0;
end;

procedure TForm1.CBchoixChange(Sender: TObject);
var                                                                           Je cherche l'indice de l'élément
 i : integer;                                                                 sélectionné dans le combo

begin
  i := CBchoix.itemindex;
  Ldiplome.caption := descrip[i].diplome;
  Lheures.caption := descrip[i].heures;                                  Je complète les labels avec les
  Linscription.caption := descrip[i].inscription;                        informations qui viennent du tableau
  Lamicale.caption := descrip[i].amicale;
  Lniveau.caption := descrip[i].niveau;
end;

end.

Ces combobox ont des options intéressantes :

               la propriété style permet de faire apparaître la flèche ( par défaut ), ce qui permet à l'utilisateur
                d'entrer une valeur personnelle dans la liste. ( csdropdown). Si vous voulez interdire l'inscription
                d'une valeur, vous choisissez l'option 'csdropdownlist'. Il est possible également de choisir
                'cssimple' qui supprime la flèche.
               la propriété dropdowncount permet de fixer le nombre d'éléments visibles simultanément

4.4. Les boîtes à listes ( listbox ).

Ce que nous avons vu avec les combobox est valable avec les listbox. Toutefois, la fenêtre d'une listbox est
toujours ouverte ( déroulée ). Il faut en tenir compte dans les applications. La listbox demande moins de
manipulation de la part de l'utilisateur final mais occupe plus de place dans votre fenêtre.

Exercice 404.           Votre programme doit comporter 3 listbox ou combobox qui permettent de sélectionner une
date comprise entre le 01/01/1940 et le 31/12/2101. La date doit être vérifiée à chaque modification d'un des
combobox ( ou listbox ) en tenant compte des années bissextiles ( les années bissextiles sont les divisibles par 4
sauf s'il s'agit de siècles non divisibles par 400).

Exercice 405.           Même exercice, mais vous afiichez le jour de la semaine et les mois en lettres.

Exercice 406. Même exercice, mais il faut ajoutes des listbox ( ou combobox ) pour saisir l'heure avec
vérification.

Exercice 407.         Même exercice, mais vous ajoutez une zone d'édition pour saisir un nombre de secondes
que l'on peut ajouter et qui fait apparaître une nouvelle heure avec une nouvelle date à la place de la première.


Vous avez constaté que ces composants professionnalisent vos applications. Toutefois, il faudrait pouvoir
ajouter de nouvelles valeurs dans les combobox et les listbox pour qu'elles puissent apparaître lors d'un
nouveau lancement de l'application. Le prochain chapitre étudiera la création et l'utilisation.

Avant de l'aborder, voici un exercice complet qui vous permettra de voir comment évolue un programme

Exercice 408.        Réalisez une calculatrice la plus complète possible. Commencez d'une manière élémentaire
puis ajoutez des fonctionnalités. Pensez à l'aide et aux mécanismes de sécurité. Vous pouvez vous inspirer de
celle de Windows mais ne compliquez pas son utilisation en la surchargeant.




Eric.Brasseur@village.uunet.be                                                                                          36
I.E.P.S.C.F. Marche en Famenne                                             Langage orienté gestion ( partie 1)


5. LES PROCEDURES ET LES FONCTIONS.

Il n'est jamais très pratique de travailler dans un fichier source de grande taille. L'idéal est de morceler son
programme. D'une manière générale, on parlera se sous-programmes. Voici le schéma général :


 Programme appelant


                                                                                   Programme appelé
                                                                                 ( Sous-programme )

                                     appel




                                     retour




Le programme appelant lance un sous-programme qui lui rend la main à la fin de son exécution.

5.1. Avantages et inconvénients de la programmation procédurale.

Avantages :
           Il est plus simple de trouver une erreur et de la corriger dans un programme qui compte moins de
            lignes.
           Les sous-programmes écrits peuvent facilement être réutilisés dans d'autres programmes
           Vous pouvez constituer vos propres librairies de sous-programmes qui peuvent même être
            distribuées à d'autres programmeurs.

Inconvénients :
           Il faut que les sous-programmes soient bien documentés pour permettre de se souvenir de leurs
            contraintes et de leurs fonctionnement
           Les noms de ces sous-programmes doivent être parlants
           Il faut respecter certaines règles précises pour les faire fonctionner.

5.2. Les sous-programmes en langage Pascal.

En Pascal, les sous-programmes portent le nom de procédures et de fonctions.

Elles se différencient par le fait qu'une fonction retourne une valeur au programme appelant tandis que la
procédure ne le fait pas.

En Delphi, nous connaissons déjà les procédures événementielles ( déclenchées lors d'un clic sur un bouton, …).
Nous allons construire nos propres procédures et fonctions qui ne seront pas événementielles.



Eric.Brasseur@village.uunet.be                                                                                     37
I.E.P.S.C.F. Marche en Famenne                                        Langage orienté gestion ( partie 1)



Il faut tout d'abord respecter absolument cers trois règles :

             Déclaration de la procédure ou de la fonction dans la partie interface du programme appelant.
             Développement de la procédure ou de la fonction dans la partie implémentation du programme
              appelant.
             Appel de la procédure ou de la fonction depuis le programme appelant ( depuis une procédure
              événementielle du programme appelant ).

Nous allons commencer par un exemple :

Imaginons un programme qui écrit deux fois bonjour dans un label :




Voici le code :

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 StdCtrls;

type
 TForm1 = class(TForm)
  Bdemarre: TButton;
  Laffiche: TLabel;
  procedure BdemarreClick(Sender: TObject);
 private
  { Déclarations privées}                                            1. Déclaration
  procedure inscrit;
 public
  { Déclarations publiques}
 end;

var


Eric.Brasseur@village.uunet.be                                                                              38
I.E.P.S.C.F. Marche en Famenne                                         Langage orienté gestion ( partie 1)


 Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.BdemarreClick(Sender: TObject);
begin
  laffiche.caption := laffiche.caption + 'Programme normal.' + #13;
  inscrit;                                                                           3. Appel
  inscrit;
  laffiche.caption := laffiche.caption + 'Vous avez vu ?';
end;

procedure TForm1.inscrit;
begin
                                                                                     2. Développement
  laffiche.caption := laffiche.caption + 'Dans ma procédure.' + #13;
end;
end.


J'ai déclaré ma procédure dans les variables privates comme si c'était une variable normale. Dans la partie
implémentation, j'ai développé son code ( son nom est précédé du nom de la fenêtre concernée ). Vous pouvez
placer ce développement avant ou après les procédures événementielles. Enfin, je l'appelle depuis la procédure
Tform1.BdemarreClick en citant simplement son nom.

Voici une procédure avec transmission d'informations du programme appelant vers la procédure inscrit.

Dans un Tedit, on demande le nombre d'inscriptions que la procédure doit faire.




Et voici le code :


unit Unit1;

interface
uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;

type
 TForm1 = class(TForm)
  Bdemarre: TButton;
  Laffiche: TLabel;
  Enombre: TEdit;
  Label1: TLabel;



Eric.Brasseur@village.uunet.be                                                                               39
I.E.P.S.C.F. Marche en Famenne                                         Langage orienté gestion ( partie 1)


  procedure BdemarreClick(Sender: TObject);
 private
  { Déclarations privées}                               Déclaration : en spécifiant que la procédure recevra un
  procedure inscrit(nbrec : integer);                   integer qu'elle placera automatiquement dans sa variable
 public                                                 locale nbrec .
  { Déclarations publiques}
 end;

var
 Form1: TForm1;
 nombre : integer;

implementation

{$R *.DFM}

procedure TForm1.BdemarreClick(Sender: TObject);
begin
  nombre := strtoint(enombre.text);
  laffiche.caption := laffiche.caption + 'Programme normal.' + #13;
  inscrit(nombre);                                                               Appel
  laffiche.caption := laffiche.caption + 'Vous avez vu ?';
end;

procedure TForm1.inscrit;                                     Développement avec déclaration d'une variable
var                                                           locale i. Vous remarquerez que je n'ai pas besoin de
  i : integer;                                                déclarer nbrec.
begin
  for i := 1 to nbrec do
    begin
     laffiche.caption := laffiche.caption + 'Dans ma procédure.' + #13;
    end;
end;
end.

Voici sensiblement le même exercice avec transmission de la chaîne à afficher par la procédure.




Eric.Brasseur@village.uunet.be                                                                               40
I.E.P.S.C.F. Marche en Famenne                                   Langage orienté gestion ( partie 1)




Voici le code associé :

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 StdCtrls;

type
 TForm1 = class(TForm)
  Bdemarre: TButton;
  Laffiche: TLabel;
  Enombre: TEdit;
  Label1: TLabel;
  Etexte: TEdit;
  Label2: TLabel;
  procedure BdemarreClick(Sender: TObject);
 private
  { Déclarations privées}
  procedure inscrit(nbrec : integer; inscription : string);
 public
  { Déclarations publiques}
 end;

var
 Form1: TForm1;
 nombre : integer;
 texte : string;

implementation

{$R *.DFM}

procedure TForm1.BdemarreClick(Sender: TObject);
begin
 nombre := strtoint(enombre.text);
 texte := etexte.text;



Eric.Brasseur@village.uunet.be                                                                         41
I.E.P.S.C.F. Marche en Famenne                                              Langage orienté gestion ( partie 1)


  laffiche.caption := laffiche.caption + 'Programme normal.' + #13;
  inscrit(nombre, texte);
  laffiche.caption := laffiche.caption + 'Vous avez vu ?';
end;

procedure TForm1.inscrit;
var
  i : integer;
begin
  for i := 1 to nbrec do
    begin
     laffiche.caption := laffiche.caption + inscription + #13;
    end;
end;
end.

Il est essentiel de transférer les paramètres dans le bon ordre et en respectant les types.

Une procédure peut elle-même faire appel à une autre procédure. Il en va de même avec une fonction.
Voici un exercice faisant appel à une fonction : celle qui calcule la racine d'un réel à l'indice réel.




unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 StdCtrls;

type
 TForm1 = class(TForm)
  Bdemarre: TButton;
  Laffiche: TLabel;
  Eradicand: TEdit;
  Label1: TLabel;
  Eindice: TEdit;
  Label2: TLabel;
  procedure BdemarreClick(Sender: TObject);
 private
  { Déclarations privées}
  nombre : real;
  function calcule(radicand, indice : real): real;                   Déclaration de la fonction avec retour d'un réel
 public
  { Déclarations publiques}



Eric.Brasseur@village.uunet.be                                                                                    42
I.E.P.S.C.F. Marche en Famenne                                         Langage orienté gestion ( partie 1)


 end;

var
 Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.BdemarreClick(Sender: TObject);
begin                                                                                 Le nombre renvoyé par la
 nombre := calcule(strtofloat(Eradicand.text),strtofloat(Eindice.text));              fonction est placé dans nombre
 laffiche.Caption := floattostr(nombre);                                              ( variable privée )
end;

function TForm1.calcule;

begin                                                            La variable result ne doit pas être déclarée. Elle existe
  result := exp(1 / indice * ln(radicand));                      pour permettre le retour du résultat calculé dans la
end;                                                             fonction.
end.
5.2. Avançons d'un pas dans la programmation modulaire.

Nous allons recommencer le programme précédent en retirant cette fonction calcule de notre unité pour la placer
dans une autre. Voici le source complet :

unit Principal; { programme principal}

interface
uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 StdCtrls, Biblio;
type                                                            J'ajoute les fonctions et procédures qui se
 TForm1 = class(TForm)                                          trouvent dans biblio
   Bdemarre: TButton;
   Laffiche: TLabel;
   Eradicand: TEdit;
   Label1: TLabel;
   Eindice: TEdit;
   Label2: TLabel;
   procedure BdemarreClick(Sender: TObject);
 private
   { Déclarations privées}
   nombre : real;

 public
  { Déclarations publiques}
 end;
var
 Form1: TForm1;
implementation

{$R *.DFM}

procedure TForm1.BdemarreClick(Sender: TObject);                                   Appel de la fonction
begin                                                                              comme précédemment
 nombre := calcule(strtofloat(Eradicand.text),strtofloat(Eindice.text));
 laffiche.Caption := floattostr(nombre);
end;
end.



Eric.Brasseur@village.uunet.be                                                                                 43
I.E.P.S.C.F. Marche en Famenne                                          Langage orienté gestion ( partie 1)



unit Biblio; { bibliothèque de fonctions et procédures }

interface                                                                           On sera amené très
                                                                                    souvent à utiliser la
function calcule(radicand, indice : real): real;                                    clause uses ici aussi

implementation

function calcule;

begin
  result := exp(1 / indice * ln(radicand));
end;

end.
program Project1;

uses
 Forms,
 principal in 'principal.pas' {Form1},                            Remarquez : déclaration d'une
 biblio in 'biblio.pas';                                          unité sans fenêtre. Cette
{$R *.RES}                                                        déclaration est insérée d'office par
begin                                                             DELPHI.
 Application.Initialize;
 Application.CreateForm(TForm1, Form1);
 Application.Run;
end.

Pour créer une unité sans qu'une nouvelle fiche soit créée, vous aller en nouveau, nouvelle unité.
Cette technique nous permet de constituer notre propre bibliothèque de procédures et fonctions.
Nous ne sommes toutefois pas encore au bout de nos peines, il reste encore quelques difficultés à vaincre.

5.3. Le passage des paramètres à une procédure ou fonction.

Nous allons construire une bibliothèque contenant une procédure qui permet de permuter le contenu de deux
variables ( de même type ). Nous écrirons également le programme pour tester cette procédure.




Eric.Brasseur@village.uunet.be                                                                                44
I.E.P.S.C.F. Marche en Famenne                                   Langage orienté gestion ( partie 1)


program transparam;
uses
 Forms,
 progprincipal in 'progprincipal.pas' {Form1},
 progsecond in 'progsecond.pas';

{$R *.RES}

begin
 Application.Initialize;
 Application.CreateForm(TForm1, Form1);
 Application.Run;
end.
unit progprincipal;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 StdCtrls, progsecond;

type
 TForm1 = class(TForm)
  Label1: TLabel;
  EX: TEdit;
  EY: TEdit;
  Label2: TLabel;
  Label3: TLabel;
  Xapres: TLabel;
  Yapres: TLabel;
  Label10: TLabel;
  Label12: TLabel;
  Label13: TLabel;
  BDemarre: TButton;
  Bquitter: TButton;
  procedure BquitterClick(Sender: TObject);
  procedure BDemarreClick(Sender: TObject);
  procedure FormCreate(Sender: TObject);
 private
  { Déclarations privées}
  nombrex, nombrey : real;
 public
  { Déclarations publiques}
 end;

var
 Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.BquitterClick(Sender: TObject);
begin
  application.terminate;
end;

procedure TForm1.BDemarreClick(Sender: TObject);
begin
 nombrex := strtofloat(EX.text);



Eric.Brasseur@village.uunet.be                                                                         45
I.E.P.S.C.F. Marche en Famenne                                          Langage orienté gestion ( partie 1)


  nombrey := strtofloat(EY.text);                                          Appel de la procédure
  permute(nombrex,nombrey);
  xapres.caption := floattostr(nombrex);
  yapres.caption := floattostr(nombrey);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
                                                                           Place le curseur sur la
  form1.activecontrol := EX;
                                                                           zone Tedit EX
end;

end.

unit progsecond;
interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 StdCtrls ;
                                                                                         Appel d'une boîte de dialogue
procedure permute(xx, yy : real);                                                        recevant dans l'ordre :
                                                                                              un message
implementation                                                                                le type de boîte
                                                                                              les boutons affichés
procedure permute(xx, yy : real);                                                             l'aide contextuelle
var
 tampon : real;
begin
 messagedlg('Valeur de X dans la procédure avant permutation : ' + floattostr(xx),
   mtinformation,[mbok],0);
 messagedlg('Valeur de Y dans la procédure avant permutation : ' + floattostr(yy),
   mtinformation,[mbok],0);
 tampon := xx;                                                       Permutation de 2 valeurs par
 xx := yy;                                                           l'intermédiaire d'une troisième
 yy := tampon;
 messagedlg('Valeur de X dans la procédure après permutation : ' + floattostr(xx),
   mtinformation,[mbok],0);
 messagedlg('Valeur de Y dans la procédure après permutation : ' + floattostr(yy),
   mtinformation,[mbok],0);
end;
end.

On constate donc :

            que les valeurs de x et de y sont bien transmises à xx et yy
            que la procédure de permutation effectue correctement la permutation de xx et de yy
            que les valeurs de x et de y du programme principal ne sont pas permutées au retour de la procédure

Pourquoi ?

Ce que nous venons de faire s'appelle une transmission       des paramètres par valeurs.
Les valeurs de la procédure (xx, yy, tampon ) sont des variables locales qui disparaissent de la mémoire au
moment de la fermeture de la procédure. Il est manifeste que ces variables n'ont rien transmis aux variables
correspondantes du programme appelant. Si vous utilisez les noms x et y au lieu de xx et yy, l'effet sera le
même. Il faut donc trouver une méthode qui permette de modifier , quand c'est nécessaire, les variables du
programme appelant.

Cette méthode existe et s'appelle la transmission      des paramètres par adresses.


Eric.Brasseur@village.uunet.be                                                                                 46
I.E.P.S.C.F. Marche en Famenne                                              Langage orienté gestion ( partie 1)


Elle consiste à passer l'adresse en RAM des variables x et y du programme appelant et d'effectuer à cet endroit
les modifications demandées. Les variables de la procédure seront celles du programme appelant. Il suffit
d'écrire en interface et en implémentation de ma bibliothèque :

procedure permute(var xx, yy : real); Testez cette façon de faire.

Il est possible de transmettre des variables par valeurs et par adresses dans la même procédure en commençant
par les variables transmises par valeurs. Il faut toujours se poser la question de savoir si les variables transmises
doivent être modifiées ou non. Certains langages privilégient une ou l'autre façon.

Exercice 501 : Constituez une bibliothèque personnelle comprenant les procédures et fonctions suivantes :
            Conversion d'un entier en base 10 vers binaire
            Conversion d'un entier binaire vers base 10
            Conversion d'un entier en base 10 vers hexadécimal
            Conversion d'un entier hexadécimal en base 10
            Conversion d'un entier hexadécimal en binaire
            Conversion d'un entier binaire en hexadécimal
            Conversion d'un angle en radians en degrés décimaux
            Conversion d'un angle en degrés décimaux en radians
            Conversion d'un angle en degrés décimaux en degrés, minutes, secondes
            Conversion d'un angle en degrés, minute, seconde en degrés décimaux
            Conversion des degrés Celsius en degrés Fahrenheit
            Conversion des degrés Fahrenheit en degrés Celsius ( Celsius = ( Fahrenheit Ŕ 32 ) * 5 / 9
            Transformation d'un caractère en majuscule ( y compris les caractères accentués )
            Recherche du maximum de deux nombres
            Recherche du minimum de deux nombres


Vous écrirez également le ou les programmes pour tester ces fonctions et procédures.


 On peut passer un tableau comme paramètre à une procédure ou à une fonction
mais la déclaration de type et de nom de ce tableau ne se fait que dans la bibliothèque,
dans la partie interface juste après les uses. Il ne faut absolument pas le faire dans le
programme appelant.

5.4. La récursivité.

Un sous-programme est récursif s'il s'appelle lui-même.

Ceci peut paraître assez surprenant : comment arrêter un programme si une fonction s'appelle elle-même ? Il
faut absolument construire ses fonctions avec un test interne de fin. Schématiquement, on peut imaginer ceci :


Appelant                     fonction recurse       fonction recurse                                 fonction recurse

……..                           ……..                     ……..                                            ……..
…..
……..                           …….                      …….                                             …….
…….                1           Recurse          2       Recurse        3                    n           Recurse
…….                            …….                      …….                                             …….
                               ……                       ……      **     **************                   ……
 Recurse
                  2n-1                          2n-2                       2n-3             n+1
 …….                           ……                       ……                                              ……
 …….
 …….
 …….



Eric.Brasseur@village.uunet.be                                                                                      47
I.E.P.S.C.F. Marche en Famenne                                                Langage orienté gestion ( partie 1)




La dernière exécution de la fonction recurse ne s'appelle plus. Le test interne l'en empêche. Remarquons que
toutes les parties qui précèdent l'auto-appel de la fonction sont exécutées successivement et que toutes les parties
inférieures sont exécutées successivement après dans l'ordre inverse. En somme, la première fonction appelée
est la dernière terminée. On peut comparer ceci à une pile d'assiette répondant à l'expression LIFO (last in, first
out). Cette façon de faire a pour conséquence :

            les variables locales de chaque fonction ou procédure ne sont libérées qu'au moment où la fonction
             ou procédure est totalement exécutée
            nous allons donc avoir un empilement de ces variables dans la mémoire ( avec un risque de
             dépassement de mémoire )
            nous allons avoir un empilement des codes de retour
            la présence du test interne est indispensable pour imposer la fin de l'auto-appel

Rien de tel qu'un exercice pour comprendre cette théorie.

Ecrivons par récursivité la recherche du factoriel d'un nombre naturel. ( ! 5 = 5 * 4 * 3 * 2 * 1 ).

Il est intéressant de voir quand les variables locales ont été manipulées :




program Recursivite;

uses
 Forms,
 progprinc in 'progprinc.pas' {Form1},
 progsecond in 'progsecond.pas';


Eric.Brasseur@village.uunet.be                                                                                      48
I.E.P.S.C.F. Marche en Famenne                                   Langage orienté gestion ( partie 1)



{$R *.RES}

begin
 Application.Initialize;
 Application.CreateForm(TForm1, Form1);
 Application.Run;
end.
unit progprinc;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 StdCtrls, progsecond;

type
 TForm1 = class(TForm)
  Label1: TLabel;
  EDonne: TEdit;
  Label2: TLabel;
  Lfinal: TLabel;
  Bcalculer: TButton;
  Bvider: TButton;
  Bquitter: TButton;
  GB1: TGroupBox;
  GB2: TGroupBox;
  Lnombre1: TLabel;
  Lnombre2: TLabel;
  Lresultat1: TLabel;
  Lresultat2: TLabel;
  Label3: TLabel;
  Label4: TLabel;
  Label5: TLabel;
  Label6: TLabel;
  procedure BquitterClick(Sender: TObject);
  procedure BviderClick(Sender: TObject);
  procedure FormCreate(Sender: TObject);
  procedure BcalculerClick(Sender: TObject);
 private
  { Déclarations privées}
 public
  { Déclarations publiques}
 end;

var
 Form1: TForm1;                                                 Nombre recevra la base de calcul
 nombre, resultat : int64;                                      Resultat fournira le factoriel calculé

implementation

{$R *.DFM}

procedure TForm1.BquitterClick(Sender: TObject);
begin
 application.terminate;
end;

procedure TForm1.BviderClick(Sender: TObject);
begin



Eric.Brasseur@village.uunet.be                                                                           49
I.E.P.S.C.F. Marche en Famenne                                      Langage orienté gestion ( partie 1)


  Edonne.text := '';
  Lfinal.caption := '';
  Lresultat1.caption := '';
  Lresultat2.caption := '';
  Lnombre1.caption := '';
  Lnombre2.caption := '';
  form1.activecontrol := Edonne;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  form1.activecontrol := Edonne;
end;

procedure TForm1.BcalculerClick(Sender: TObject);
begin
  nombre := strtoint(Edonne.text);
  resultat := 1;                                                   D'autres tests de validité sont à
  if (nombre >= 1) then                                            effectuer. (integer ? )
     begin
       factoriel(nombre, resultat);
       Lfinal.caption := inttostr(resultat);
     end
  else showmessage('Calcul impossible');                           Appel de la procédure
end;

end.


unit progsecond;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 StdCtrls;

procedure factoriel(nbre : int64; var resu : int64);               Seul le résultat doit être modifié

implementation
                                                                   Nous devrons écrire directement
uses progprinc;                                                    dans form1 qui est déclaré dans
                                                                   l'appelant. Ne faire qu'en tests.
procedure factoriel(nbre : int64; var resu : int64);
begin
 form1.lnombre1.caption := form1.lnombre1.caption + inttostr(nbre) + #13;
 form1.lresultat1.caption := form1.lresultat1.caption + inttostr(resu) + #13;              Affichage des
 if (nbre > 1) then factoriel(nbre - 1, resu);                                             modifications de nombre
 resu := resu * nbre;                                                                      et resultat avant et après
 form1.lnombre2.caption := form1.lnombre2.caption + inttostr(nbre) + #13;                  appel de la procédure
 form1.lresultat2.caption := form1.lresultat2.caption + inttostr(resu) + #13;              pour la tester
end;
end.

                                                                   Calcule le produit



                                                                   Test avant appel de la procédure




Eric.Brasseur@village.uunet.be                                                                               50
I.E.P.S.C.F. Marche en Famenne                                          Langage orienté gestion ( partie 1)


Attention : le uses du progprinc dans progsecond ne peut se faire dans la partie interface car on aurait un
appel circulaire. Il faut éviter de faire référence à l'appelant dans l'appelé car nos procédures et fonctions
devraient servir dans plusieurs programmes ( dont les appelants porteraient des noms différents ).
N'utiliser cette méthode que dans la phase de tests de votre programmation.
Si vous supprimer les quatre lignes de test, cet uses devient inutile.

Exercice 502.
Ecrire le programme qui permet de saisir deux nombres au clavier et qui fournit leur P.G.C.D. ( en utilisant une
bibliothèque comprenant la méthode récursive dont vous trouverez le détail ci-dessous ).

Rappel : le P.G.C.D. de deux nombres X et Y est le plus grand nombre qui divise à la fois X et Y.

Procédé : on divise ( division entière ) le plus grand ( X ) des deux nombres par le plus petit ( Y ). On affecte
ensuite à X le nombre Y et à Y le reste de la division entière. On recommence alors l'opération jusqu'à ce que Y
soit égal à 0. X est alors le P.G.C.D. de X et Y de départ.

Exemple : soit X = 108 et Y = 84.

            on divise X par Y. Le reste est 24. X devient 84 et Y devient 24.
            on divise X par Y. Le reste est 8. X devient 24 et Y devient 8.
            on divise X par Y. Le reste est 0. X devient 8 et Y devient 0.

LE P.G.C.D. de 108 et 84 est 8.


Exercice 503.
Réécrivez le programme qui permet de donner la suite de Fibonacci par récursivité.




Eric.Brasseur@village.uunet.be                                                                                 51
I.E.P.S.C.F. Marche en Famenne                                            Langage orienté gestion ( partie 1)


6. LES FICHIERS.
Il est très important de pouvoir stocker des informations qui pourront être utilisées à plusieurs reprises même si
l'ordinateur a été éteint. Ces informations sont regroupées dans des fichiers ( en anglais : file ) écrits sur un
support. Ce support peut-être de plusieurs types :
              papier
              bande magnétique
              disques durs ou disquettes
              CD ROM, CD RAM, DVD, …
Certains supports sont plus pratiques que d'autres. Il est évident que sur papier ou sur bandes magnétiques, si
vous cherchez une information, il est nécessaire de lire toutes celles qui se trouvent avant. Les autres supports
permettent d'accéder directement à une information ( si nous avons correctement organisé notre fichier et
implémenté notre programme ). Nous insisterons sur ce type de fichier.

6.1. Déclaration.

Un fichier est composé d'un certain nombre d'enregistrements ( en anglais : record ). Tous les enregistrements
ont la même taille et la même structure ( il est possible de déroger à cette règle, mais ceci complique
considérablement la manipulation ). Cette structure doit être déclarée avant le fichier.
Voici un exemple :

Type
client = record
         Code      : string[6];
         Nom       : string[15];
         Prenom    : string[15];
         Adresse   : string[25];
         Cpostal   : string[5];
         Localit   : string[15];
         Pays      : string[2];
         CA        : longint;
End;

Chaque fiche du fichier comprendra ces 8 variables. On les appelle parfois champs ( field en anglais ).
Chaque fiche prendra 94 bytes ( octets ) sur le support. Chaque string occupe sa place + 1 byte tandis que les
zones numériques occupent juste leur espace mémoire ( 4 bytes pour un longint ).

Il faut ensuite déclarer le fichier

Fclient : file of client;

Il ne faut pas définir le nombre de fiches, car un fichier peut compter un nombre illimité ( en théorie ) de
records. Fclient est défini comme un fichier de " client " dans le sens que chaque record a la structure de type
 " client ".

Il nous reste encore une étape : n'oublions pas que l'ordinateur travaille toujours en RAM et pas directement sur
le support magnétique ( ou autre ). Il va falloir créer une variable qui a la même structure que les
enregistrements du fichier. Rien de plus facile :

Unclient : client;

Pour accéder à chaque champ composant la variable " unclient ", on écrit par exemple :

Unclient.nom := 'Brasseur';

Pour lire le contenu du fichier " fclient ", nous lirons un enregistrement du fichier dans la variable " unclient ".
Inversément, pour écrire un enregistrement dans le fichier " fclient ", nous écrirons la variable " unclient " dans
le fichier.
Il est évident qu'on peut travailler avec plusieurs fichiers simultanément.


Eric.Brasseur@village.uunet.be                                                                                     52
I.E.P.S.C.F. Marche en Famenne                                               Langage orienté gestion ( partie 1)


6.2. Ouverture et fermeture du fichier.

Pour travailler dans un fichier, il faut qu'il soit ouvert. Ceci nécessite les étapes suivantes :

             assignation en début du programme du nom physique ( nom que le fichier porte dans le système
              d'exploitation : ex. : "ficcli.dat" ) au nom logique ( nom utilisé dans le programme : ex. : " fclient " )
              de cette façon :

              assignfile(fclient, ficcli.dat);

              ouverture proprement dite : il est possible d'ouvrir un fichier en écriture seulement, en lecture
              seulement ou en mise à jour. Nous travaillerons en mise à jour de cette façon :

              reset(fclient);

Il est prudent de tester si le fichier existe avant l'ouverture proprement dite car tenter d'ouvrir un fichier en
lecture seule ou en mise à jour s'il n'existe pas provoque une erreur fatale et un plantage du programme. Si bien
que lors de la première ouverture du fichier dans un programme, on écrit plutôt :

             {$i-}
              reset(fclient);
             {$I+}
              if ioresult <> 0 then rewrite(fclient);
              closefile(fclient);


{$i-} intercepte l'erreur d'ouverture d'un fichier, {$i+} restaure la non-interception de l'erreur.
La variable ioresult reçoit 0 si l'ouverture s'est correctement effectuée. Si ce n'est pas le cas, nous ouvrons le
fichier en écriture seulement ( rewrite(fclient) ) , mais ce type d'ouverture efface tout ancien fichier qui porterait
le même nom et en crée un nouveau entièrement vide..
Nous fermons (closefile(fclient)) ensuite le fichier, dans toutes les conditions. Plus tard dans le programme, il
suffit d'ouvrir en mise à jour (reset(fclient)).

Un fichier ne peut être ouvert deux fois simultanément mais peut être ouvert et fermé plusieurs fois dans le
même programme. Une fois le fichier fermé, toute tentative d'écriture ou lecture dans ce fichier provoque une
erreur.

6.3. Lecture et écriture dans un fichier.

Vous trouverez plus tard de plus amples explications sur les méthodes d'accès aux enregistrements des fichiers (
cours d'analyse ). Retenez simplement que si vous avez un fichier en accès séquentiel, il faut lire tous les
enregistrements qui précèdent celui que vous cherchez avant d'écrire ou de lire. En accès direct, vous donnez la
position de l'enregistrement puis vous lisez ou vous écrivez à cet endroit. Le problème est de connaître ce
numéro d'enregistrement.

Dans un fichier, le premier enregistrement porte toujours le numéro 0. En réalité, comme vous allez le voir, ceci
va simplifier notre travail; représentons schématiquement un fichier comprenant 6 records : chaque record a une
taille de 94 bytes. Le premier byte portera aussi le numéro 0.



   Rec 0            Rec 1            Rec 2           Rec3             Rec 4            Rec 5
   Byte 0           Byte 94          Byte 188        Byte 282         Byte 376         Byte 470




L'instruction seek(fclient, numcli) avec par exemple numcli qui vaut 3 nous positionne au début de rec3, c'est à
dire sur le byte 282. L'ordinateur connaît la taille d'un enregistrement et multiplie cette taille par numcli, ce qui
donne le byte 282. Nous pourrons ensuite lire rec3 ou écrire sur rec3.


Eric.Brasseur@village.uunet.be                                                                                       53
I.E.P.S.C.F. Marche en Famenne                                              Langage orienté gestion ( partie 1)


Nous pourrons lire l'enregistrement en écrivant :

Read(fclient, unclient);

Nous travaillerons ensuite sur la variable unclient. Inversement, nous pourrons écrire de cette manière :

Write(fclient, unclient);


        ATTENTION : chaque lecture d'un enregistrement fait avancer le pointeur
                  d'enregistrement sur l'enregistrement suivant.

Si nous voulons ajouter un enregistrement, c'est toujours à la fin du fichier. DELPHI dispose d'une instruction
qui donne la taille en records du fichier ( la taille réelle, pas le numéro du dernier enregistrement). Si nous
écrivons

Nbenreg := filesize(fclient);

Nbenreg recevra la valeur 6. Pour ajouter un enregistrement, il suffira de se positionner en

Seek(fclient, nbenreg); ou bien seek(fclient, filesize(nbenreg));

Puis

Write(fclient, unclient);

6.4. Exemple : le fichier client ( version 1 ).

A partir de la description donnée plus haut, nous allons programmer une gestion de fichier qui va s'améliorer
petit à petit. Nous saisirons les enregistrements un à un et nous devrons valider l'enregistrement chaque fois (
par un bouton qui entraînera une boîte à message ). Si le champ nom ou le champ prénom est vide,
l'enregistrement ne peut se faire et l'utilisateur est prévenu par un message. Pour faciliter la saisie, la zone
recevra la priorité et chaque autre zone pourra être atteinte dans l'ordre par un TAB. Il est possible de lister les
enregistrements dans une listbox ( séquentiellement ou par ordre croissant ).




Eric.Brasseur@village.uunet.be                                                                                         54
I.E.P.S.C.F. Marche en Famenne                                   Langage orienté gestion ( partie 1)


program gestionclient;

uses
 Forms,
 ficheclient in 'ficheclient.pas' {Form1};

{$R *.RES}
begin
 Application.Initialize;
 Application.CreateForm(TForm1, Form1);
 Application.Run;
end.

unit ficheclient;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 StdCtrls;

type
 client = record
     Code : string[6];
     Nom : string[15];                                                       Déclaration du type client
     Prenom : string[15];                                                    correspondant à un
     Adresse : string[25];                                                   enregistrement dans mon
     Cpostal : string[5];                                                    fichier
     Localit : string[15];
     Pays : string[2];
     CA : longint;
 End;
 TForm1 = class(TForm)
  Label1: TLabel;
  Label2: TLabel;
  Label3: TLabel;
  Label4: TLabel;
  Label5: TLabel;
  Label6: TLabel;
  Label7: TLabel;
  Label8: TLabel;
  Ecode: TEdit;
  Enom: TEdit;
  Eprenom: TEdit;
  Eadresse: TEdit;
  Ecp: TEdit;
  Elocalite: TEdit;
  Epays: TEdit;
  Eca: TEdit;
  Label9: TLabel;
  Lnum: TLabel;
  Benregistrer: TButton;
  Blister: TButton;
  Bquitter: TButton;
  Listclient: TListBox;
  procedure FormCreate(Sender: TObject);
  procedure Formclose(Sender: TObject; var Action: TCloseAction);
  procedure BquitterClick(Sender: TObject);
  procedure BenregistrerClick(Sender: TObject);
  procedure BlisterClick(Sender: TObject);



Eric.Brasseur@village.uunet.be                                                                            55
I.E.P.S.C.F. Marche en Famenne                                        Langage orienté gestion ( partie 1)



 private
  { Déclarations privées}
 public
  { Déclarations publiques}
 end;

var
 Form1: TForm1;
 fclient : file of client;
 unclient : client;                                                    Boîte à message du type
 numero, n, i : longint;                                               Confirmation à 2 boutons.

implementation

{$R *.DFM}

procedure TForm1.BenregistrerClick(Sender: TObject);
begin
  if(messagedlg('Souhaitez-vous enregistrer la fiche de ce client ?', mtconfirmation,
      [mbok,mbcancel],0) = mrok)
     then begin
       if(enom.text = '') or (eprenom.text = '')                       Si message reçu est OK
          then messagedlg('Fiche mal remplie ! ', mterror,[mbok],0)
          else
            begin
                                                                       Boîte à message du type Erreur
              unclient.code := ecode.text;
              unclient.nom := enom.text;
              unclient.prenom := eprenom.text;
              unclient.adresse := eadresse.text;                       Chaque saisie dans mes Tedit est
              unclient.cpostal := ecp.text;                            placée dans la variable tampon
              unclient.localit := elocalite.text;
                                                                       unclient
              unclient.Pays := epays.Text;
              unclient.CA := strtoint(eca.text);
              seek(fclient, numero);                                   Positionnement à la fin du fichier
              write(fclient, unclient);                                puis écriture depuis la variable
              lnum.caption := inttostr(numero + 1);                    tampon
              numero := numero + 1;
              ecode.text := '';
              enom.text := '';                                         Affichage du nombre
              eprenom.text := '';                                      d'enregistrement
              eadresse.text := '';                                      + incrémentation
              ecp.text := '';                                          + mise à blanc pour saisir
              elocalite.text := '';                                    l'enregistrement suivant
              epays.text := '';
              eca.text := '0';
            end;                                                       Boîte à message du type Attention
         end
     else begin
           messagedlg('Vous avez annulé l''enregistrement', mtwarning, [mbok],0);
         end;
  form1.activecontrol := enom;                                         Replace le curseur dans Enom
end;

procedure TForm1.BquitterClick(Sender: TObject);
begin
  closefile(fclient);
  application.terminate;
end;




Eric.Brasseur@village.uunet.be                                                                              56
I.E.P.S.C.F. Marche en Famenne                                             Langage orienté gestion ( partie 1)


procedure TForm1.FormClose(Sender : TObject; var Action : TCloseAction);
begin
  closefile(fclient);                                      En cas de fermeture par une autre
  application.terminate;                                   méthode que QUITTER, le fichier
end;                                                       est bien fermé.

procedure TForm1.FormCreate(Sender: TObject);
begin
  assignfile(fclient,'client.dat');
  {$i-}                                                                 Je suis certain de passer par cette
  reset(fclient);                                                       procédure. J'y effectue donc mes
  {$i+}                                                                 tentatives d'ouverture de fichier.
  if ioresult <> 0 then rewrite(fclient);                               Le positionne eca à 0 ce qui
  numero := filesize(fclient);                                          diminue les risques d'erreurs de
  eca.text := '0';                                                      conversion. Ceci n'empêche pas
end;                                                                    de prévoir un contrôle.

procedure TForm1.BlisterClick(Sender: TObject);
begin
                                                                    Mise à blanc de la liste
  listclient.clear;
  n := 0;
  while (n < filesize(fclient)) do
    begin
      seek(fclient, n);
      read(fclient, unclient);
      listclient.items.add(unclient.nom + ' ' + unclient.prenom + ' ' +        Positionnement,
          unclient.adresse + ' ' + unclient.Cpostal + ' ' +                    lecture et placement
          unclient.Localit + ' ' + unclient.Pays + ' ' +                       dans la liste par
          inttostr(unclient.ca));                                              concaténation
      n := n + 1;
    end;
end;

end.

6.5. Positionnement et affichage d'un record sélectionné.

Cette fois, nous allons permettre à l'utilisateur de rechercher un client sur le critère "nom". L'utilisateur entrera
dans la zone nom le début du nom recherché. Chaque client qui correspondra sera affiché dans la liste. Il suffira
ensuite de sélectionner ce client dans la liste pour le voir édité sur mon écran. Nous ajouterons une procédure de
recherche (liée au bouton RECHERCHER ) et une procédure de positionnement sur un record sélectionné dans
la liste. Si aucun record ne correspond au critère, un message sera affiché sur l'écran.

Nous nous servirons du code client pour récupérer le bon enregistrement. Il ne peut y avoir deux fois le même
code client. On va donc modifier la procédure BenregistrerClick pour que ce code soit attribué de manière
unique par le système. Vous devez donc empêcher l'écriture manuelle sur ecode.

Il faut également empêcher la double écriture d'un enregistrement en inhibant le bouton benregistrer quand nous
affichons un record.

Un bouton "NOUVEAU" sera inséré pour remettre les zones à blanc et permettre de saisir un nouvel
enregistrement.

Dans la liste affichée, nous ajoutons le code du client.

Avant de tester le programme, vous effacez le fichier "client.dat" dans le répertoire de votre application. Vous
remplacez également le contenu du label "Numéro d'enregistrement" par "Nombres d'enregistrements".

Voici le code des quatre procédures modifiées et l'affichage obtenu :




Eric.Brasseur@village.uunet.be                                                                                     57
I.E.P.S.C.F. Marche en Famenne                                             Langage orienté gestion ( partie 1)


procedure TForm1.BnouveauClick(Sender: TObject);
begin
  ecode.text := '';
  enom.text := '';
  eprenom.text := '';
  eadresse.text := '';                                            Remise à blanc, rétablissement du bouton
  ecp.text := '';                                                 benregistrer et placement sur ecode
  elocalite.text := '';
  epays.text := '';
  eca.text := '0';
  benregistrer.enabled := true;
  form1.activecontrol := enom;
end;

procedure TForm1.BrechercherClick(Sender: TObject);
var
  longueur, i : integer;                                           Variables locales
  test, trouve : boolean;
begin
  listclient.clear;
  n := 0;
  trouve := false;
  while (n < filesize(fclient)) do
    begin
      seek(fclient, n );                                           Comparaison caractère par caractère en
      read(fclient, unclient);                                     majuscule de la chaîne encodée et du nom du
      longueur := length(enom.text);                               client. Quand un caractère est différent ou
      test := true;                                                que nous dépassons la taille du nom, nous
      i := 1;                                                      passons au record suivant.
      while (i <= longueur) do
         begin
           if(uppercase(unclient.Nom[i]) <> uppercase(enom.text[i])) then test := false;
           i := i + 1;
         end;                                                                   Affichage si test nous affirme
      if test = true then                                                       que l'enregistrement
         begin                                                                  correspond.
          listclient.items.add(unclient.code + ' ' + unclient.nom + ' ' +
                        unclient.prenom + ' ' + unclient.adresse + ' ' +
                        unclient.Cpostal + ' ' + unclient.Localit + ' ' +
                        unclient.Pays + ' ' + inttostr(unclient.ca));
          trouve := true;
         end;
      n := n + 1;
    end;
  if(trouve = false) then messagedlg('Aucun enregistrement ne correspond.', mterror,[mbok],0);
end;
                                                                  Message d'erreur si aucun enregistrement ne
                                                                  correspond à notre requête.




La mise en majuscule n'est pas parfaite. Un bel exercice consisterait à écrire la conversion en majuscule par
une fonction majusc qui travaillerait également sur nos caractères accentués ( é, è, ë, ê, ù, û, ü, à, â, ä, ô, ö, ï,
î, ç ).
Vous trouverez une solution plus loin. Il suffit donc de remplacer ci-dessus uppercase(….) par majusc(….)
et de bien se souvenir des règles en matières de sous-programme. Cette fonction sera placée dans une autre
fiche.
On peut également faire trier la liste sur le nom et le prénom ( liste sorted ) et en plaçant le code à la fin de la
ligne, ce qui nécessite aussi une modification du copy..



Eric.Brasseur@village.uunet.be                                                                                     58
I.E.P.S.C.F. Marche en Famenne                                        Langage orienté gestion ( partie 1)


procedure TForm1.ListclientClick(Sender: TObject);
var
  i : integer;
  test : boolean;
begin
  benregistrer.enabled := false;                                Bouton d'enregistrement supprimé.
  i := listclient.itemindex;                                    On place dans i la position de l'item
  ecode.text := copy(listclient.items[i],1,6);                  sélectionné dans listclient.
  n := 0;                                                       On y extrait le code client.
  test := true;
  while (n < filesize(fclient)) and (test = true) do
     begin
       seek(fclient,n);
       read(fclient,unclient);
       n := n + 1;
       if (unclient.code = ecode.text) then
          begin
            ecode.text := unclient.code;                        On parcourt le fichier séquentiellement
            enom.text := unclient.nom;                          pour retrouver le record sélectionné puis
            eprenom.text := unclient.prenom;                    on l'affiche dans la grille.
            eadresse.text := unclient.adresse;
            ecp.text := unclient.Cpostal;
            elocalite.text := unclient.Localit;
            epays.text := unclient.Pays;
            eca.text := inttostr(unclient.ca);
            test := false;
          end;
     end;
end;

procedure TForm1.BenregistrerClick(Sender: TObject);
var
 longueur : integer;
begin
 if(messagedlg('Souhaitez-vous enregistrer la fiche de ce client ?', mtconfirmation,
     [mbok,mbcancel],0) = mrok)
    then begin
      if(enom.text = '') or (eprenom.text = '')
        then messagedlg('Fiche mal remplie ! ', mterror,[mbok],0)
        else
          begin
            unclient.code := inttostr(numero);
            longueur := length(unclient.code);
            case longueur of                                              On transforme le numéro
              1 : unclient.code := 'C0000' + inttostr(numero);            d'enregistrement en un code
              2 : unclient.code := 'C000' + inttostr(numero);             standardisé de 6 caractères.
              3 : unclient.code := 'C00' + inttostr(numero);
              4 : unclient.code := 'C0' + inttostr(numero);
              5 : unclient.code := 'C' + inttostr(numero);
            end;
            unclient.nom := enom.text;
            unclient.prenom := eprenom.text;
            unclient.adresse := eadresse.text;
            unclient.cpostal := ecp.text;
            unclient.localit := elocalite.text;
            unclient.Pays := epays.Text;
            unclient.CA := strtoint(eca.text);
            seek(fclient, numero);
            write(fclient, unclient);
            lnum.caption := inttostr(numero + 1);



Eric.Brasseur@village.uunet.be                                                                              59
I.E.P.S.C.F. Marche en Famenne                                          Langage orienté gestion ( partie 1)


            numero := numero + 1;
            ecode.text := '';
            enom.text := '';
            eprenom.text := '';
            eadresse.text := '';
            ecp.text := '';
            elocalite.text := '';
            epays.text := '';
            eca.text := '0';
          end;
       end
    else begin
         messagedlg('Vous avez annulé l''enregistrement', mtwarning, [mbok],0);
       end;
  form1.activecontrol := enom;
end;

procedure TForm1.BlisterClick(Sender: TObject);
begin
  listclient.clear;
  n := 0;
  while (n < filesize(fclient)) do                                        J'inclus le code du client dans ma
    begin                                                                 liste.
      seek(fclient, n );
      read(fclient, unclient);
      listclient.items.add(unclient.code + ' ' + unclient.nom + ' ' +
      unclient.prenom + ' ' + unclient.adresse + ' ' +
      unclient.Cpostal + ' ' + unclient.Localit + ' ' +
      unclient.Pays + ' ' + inttostr(unclient.ca));
      n := n + 1;
    end;
end;




Eric.Brasseur@village.uunet.be                                                                                 60
I.E.P.S.C.F. Marche en Famenne                                            Langage orienté gestion ( partie 1)


Améliorations : conversion en majuscules.

unit personnelle;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;

function majusc(cara : string) : string;

implementation

function majusc(cara : string) : string;
var
caract : char;
resul : char;
begin                                                                   Transtypage ( ou casting ) du type string
caract := char(cara[1]);                                                vers le type char car case n'accepte pas
 case caract of                                                         les strings
   'a'..'z'          : resul := upcase(caract);
   'é','è','ê','ë'  : resul := 'E';
   'ù','ü','û'       : resul := 'U';
   'à','â','ä'      : resul := 'A';
   'ô','ö'          : resul := 'O';
   'î','ï'         : resul := 'I';
   'ç'             : resul := 'C'
   else              resul := caract;
 end;
result := string(resul);
                                                                        Transtypage inverse
end;

end.



procedure TForm1.BrechercherClick(Sender: TObject);
var
 longueur, i : integer;
 test, trouve : boolean;
begin
 listclient.clear;
 n := 0;
 trouve := false;
 while (n < filesize(fclient)) do
   begin
     seek(fclient, n );                                                  Utilisation de la fonction majusc
     read(fclient, unclient);
     longueur := length(enom.text);
     test := true;
     i := 1;
     while (i <= longueur) do
        begin
          if(majusc(unclient.Nom[i]) <> majusc(enom.text[i])) then test := false;
          i := i + 1;
        end;
     if test = true then
        begin
         listclient.items.add(unclient.nom + ' ' + unclient.prenom + ' ' +
                       unclient.adresse + ' ' + unclient.Cpostal + ' ' +



Eric.Brasseur@village.uunet.be                                                                                  61
I.E.P.S.C.F. Marche en Famenne                                             Langage orienté gestion ( partie 1)


                      unclient.Localit + ' ' + unclient.Pays + ' ' +
                      inttostr(unclient.ca) + ' ' + unclient.code );
         trouve := true;                                               Le code est placé en fin de l'item
        end;
      n := n + 1;
    end;
  if(trouve = false) then messagedlg('Aucun enregistrement ne correspond.', mterror,[mbok],0);
end;



procedure TForm1.ListclientClick(Sender: TObject);
var
  i : integer;
  test : boolean;
begin
  benregistrer.enabled := false;
  i := listclient.itemindex;
  ecode.text := copy(listclient.items[i],length(listclient.items[i]) - 5,6);
  n := 0;                                                                             Le code est à la fin, je vais
  test := true;                                                                       le retrouver à la fin
  while (n < filesize(fclient)) and (test = true) do
     begin
       seek(fclient,n);
       read(fclient,unclient);
       n := n + 1;
       if (unclient.code = ecode.text) then
          begin
            ecode.text := unclient.code;
            enom.text := unclient.nom;
            eprenom.text := unclient.prenom;
            eadresse.text := unclient.adresse;
            ecp.text := unclient.Cpostal;
            elocalite.text := unclient.Localit;
            epays.text := unclient.Pays;
            eca.text := inttostr(unclient.ca);
            test := false;
          end;
     end;
end;


procedure TForm1.BlisterClick(Sender: TObject);
begin
  listclient.clear;
  n := 0;
  while (n < filesize(fclient)) do
    begin
      seek(fclient, n );
      read(fclient, unclient);
      listclient.items.add(unclient.nom + ' ' + unclient.prenom + ' ' +
                    unclient.adresse + ' ' + unclient.Cpostal + ' ' +
                    unclient.Localit + ' ' + unclient.Pays + ' ' +
                    inttostr(unclient.ca) + ' ' + unclient.code);
      n := n + 1;
    end;
end;                                                                            Code placé à la fin




Eric.Brasseur@village.uunet.be                                                                                        62
I.E.P.S.C.F. Marche en Famenne                                              Langage orienté gestion ( partie 1)


6.6. Modification d'un record – Suppression d'un record – Travail multi-fichiers.

Voici une application comprenant deux fenêtres : une pour la gestion des clients et une pour la gestion des
localités.
Un client pourra être modifié ou supprimé tandis que ce ne sera pas possible de supprimer une localité ( car elle
pourrait déjà être inscrite dans le fichier des clients ). Le même dilemme se pose pour la modification mais d'une
façon moins cruciale.

Un peu de théorie.

6.6.1.     Modification d'un record.

Il faut permettre de modifier un ou plusieurs champs du record. Toutefois, le code doit être non modifiable. Les
étapes de la modification sont les suivantes :

              Positionnement sur le record à modifier.
              Lecture du record et affichage dans la fenêtre.
              Modification dans la fenêtre.
              Enregistrement dans le fichier.

Il ne faut toutefois pas oublier que le pointeur associé au fichier a avancé d'un record après la lecture. Il faudra
donc reculer d'un record avant l'enregistrement de la modification.

6.6.2.     Suppression d'un enregistrement.

Il s'agit là d'un acte assez complexe. Plusieurs possibilités existent. Elles présentent des avantages et des
inconvénients que nous allons détailler.


 R0           R1         R2            R3       R4         R5          R6          R7




                              Record à supprimer

6.6.2.1.      Méthode du tassement.

Tous les records situés à droite du record 3 sont avancés d'un rang vers la gauche. Le dernier est marqué comme
réutilisable. ( marque à définir ).


 R0           R1         R2            R3       R4         R5          R6          UTIL
                                       (R4)     (R5)       (R6)        (R7)


Avantage :
          le fichier ne comprendra qu'un nombre restreint d'enregistrements. Lors d'un ajout, les records
           marqués utilisables sont donc remplacés par les nouveaux.

Inconvénients :
           Il faut déplacer tous les records qui suivent, ce qui nécessite un temps assez long
           Il faut chercher par la fin du fichier le premier marqué utilisable quand on ajoute un record ( il
            s'agira en réalité d'une modification ).
           Dans notre application, il faut changer les codes des clients de tous les records car autrement, deux
            records pourraient porter le même code.
           Si le code du client est utilisé dans un autre fichier ( par exemple le fichier facture ) comme
            identifiant , l'identification sera fautive. Il est évident, dans ce cas, qu'on ne peut supprimer ou
            déplacer un record identifié dans un autre fichier ( une routine de contrôle est écrite ).
           Il est impossible de récupérer un record effacé par erreur.


Eric.Brasseur@village.uunet.be                                                                                         63
I.E.P.S.C.F. Marche en Famenne                                            Langage orienté gestion ( partie 1)



6.6.2.2. Méthode de la permutation avec le dernier.

Nous amenons le dernier record à la place de celui qui est supprimé et nous marquons le dernier comme
utilisable.


   R0          R1         R2          R3          R4         R5          R6          UTIL
                                      ( R7 )



Avantage :
          le fichier ne comprendra qu'un nombre restreint d'enregistrements. Lors d'un ajout, les records
           marqués utilisables sont donc remplacés par les nouveaux.
          Le remplacement prend peu de temps mais attention : il faut trouver le premier enregistrement non
           marqué utilisable.
          On ne change le code que du record transféré.

Inconvénients :
           Il faut chercher par la fin du fichier le premier marqué utilisable quand on ajoute un record ( il
            s'agira en réalité d'une modification ).
           Si le code du client est utilisé dans un autre fichier ( par exemple le fichier facture ) comme
            identifiant , l'identification sera fautive. Il est évident, dans ce cas, qu'on ne peut supprimer ou
            déplacer un record identifié dans un autre fichier ( une routine de contrôle est écrite ).
           Il est impossible de récupérer un record effacé par erreur.

6.6.2.3. Méthode du marquage utilisable en position.

Ici, nous ne déplacerons aucun record ; nous marquerons utilisable à sa position le record supprimé. Lors d'un
ajout, nous écrirons sur le premier utilisable rencontré.



   R0          R1         R2          UTIL        R4         R5          R6          R7



Avantage :
          le fichier ne comprendra qu'un nombre restreint d'enregistrements. Lors d'un ajout, les records
           marqués utilisables sont donc remplacés par les nouveaux.
          On ne change aucun code client. Il faut penser à ne pas afficher les records utilisables.

Inconvénients :
           Il faut chercher le premier marqué utilisable quand on ajoute un record ( il s'agira en réalité d'une
            modification ).
           Si le code du client est utilisé dans un autre fichier ( par exemple le fichier facture ) comme
            identifiant , l'identification sera fautive. Il est évident, dans ce cas, qu'on ne peut supprimer un
            record identifié dans un autre fichier ( une routine de contrôle est écrite ).
           Il est impossible de récupérer un record effacé par erreur.

6.6.2.4. Méthode du marquage sans réutilisation possible.

Nous ne permettons pas qu'on réutilise un record marqué comme supprimé, tous les ajouts se faiant à la fin du
fichier. La suppression du record est juste logique et non physique.


   R0          R1         R2          SUPP        R4         R5          R6          R7




Eric.Brasseur@village.uunet.be                                                                                      64
I.E.P.S.C.F. Marche en Famenne                                            Langage orienté gestion ( partie 1)


Avantage :
            On ne change aucun code de client.
            Un record effacé par erreur peut être récupéré.
            Le code source est plus simple. Il faut juste éviter d'afficher les records supprimés.
            L'ajout se fait toujours à la fin.

Inconvénients :
           Si le code du client est utilisé dans un autre fichier ( par exemple le fichier facture ) comme
            identifiant , l'identification sera fautive. Il est évident, dans ce cas, qu'on ne peut supprimer un
            record identifié dans un autre fichier ( une routine de contrôle est écrite ).
           Le fichier est de taille importante et comprend des records inutiles.


Dans l'exercice qui suit, je vais utiliser cette dernière méthode.
Exercice : créez une application capable de gérer dans une fenêtre différente un fichier des localités et d'insérer
cette localité, le code postal et le pays dans le fichier des clients. Cette application doit pouvoir supprimer ou
modifier un client.




Quand nous utilisons le bouton GEST LOC. , il s'agit simplement de la gestion des localités sans insérer cette
localité dans notre fichier client. Avec INS. LOC. , nous pourrons insérer la localité depuis l'autre fenêtre. Un
bouton supplémentaire sera disponible dans la fiche des localités. J'ai profité de la modification pour empêcher
une erreur de conversion des strings en integer. ( à 2 endroits ).




Eric.Brasseur@village.uunet.be                                                                                     65
I.E.P.S.C.F. Marche en Famenne   Langage orienté gestion ( partie 1)


Avec INS. LOC.




AVEC GEST. LOC.




Eric.Brasseur@village.uunet.be                                         66
I.E.P.S.C.F. Marche en Famenne                                   Langage orienté gestion ( partie 1)


program gestionclient;
uses
 Forms,
 ficheclient in 'ficheclient.pas' {Form1},
 personnelle in 'personnelle.pas',
 gestlocalite in 'gestlocalite.pas' {Form2};

{$R *.RES}

begin
 Application.Initialize;
 Application.CreateForm(TForm1, Form1);
 Application.CreateForm(TForm2, Form2);
 Application.Run;
end.


unit ficheclient;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 StdCtrls, personnelle;

type
 client = record
     Code     : string[6];
     Nom      : string[15];
     Prenom : string[15];
     Adresse : string[25];
     Cpostal : string[5];
     Localit : string[15];
     Pays     : string[2];
    CA        : longint;
 End;
 TForm1 = class(TForm)
  Label1: TLabel;
  Label2: TLabel;
  Label3: TLabel;
  Label4: TLabel;
  Label5: TLabel;
  Label6: TLabel;
  Label7: TLabel;
  Label8: TLabel;
  Ecode: TEdit;
  Enom: TEdit;
  Eprenom: TEdit;
  Eadresse: TEdit;
  Ecp: TEdit;
  Elocalite: TEdit;
  Epays: TEdit;
  Eca: TEdit;
  Label9: TLabel;
  Lnum: TLabel;
  Benregistrer: TButton;
  Blister: TButton;
  Bquitter: TButton;
  Listclient: TListBox;
  Brechercher: TButton;



Eric.Brasseur@village.uunet.be                                                                         67
I.E.P.S.C.F. Marche en Famenne                                 Langage orienté gestion ( partie 1)


  BNouveau: TButton;
  Binsloc: TButton;
  Bgesloc: TButton;
  Bmodifier: TButton;
  Bsupprimer: TButton;
  procedure FormCreate(Sender: TObject);
  procedure Formclose(Sender: TObject; var Action: TCloseAction);
  procedure BquitterClick(Sender: TObject);
  procedure BlisterClick(Sender: TObject);
  procedure BrechercherClick(Sender: TObject);
  procedure ListclientClick(Sender: TObject);
  procedure BnouveauClick(Sender: TObject);
  procedure BenregistrerClick(Sender: TObject);
  procedure Binslocclick(sender : TObject);
  procedure Bgeslocclick(sender : TObject);
  procedure BmodifierClick(Sender: TObject);
  procedure BsupprimerClick(Sender: TObject);
 private
  { Déclarations privées}
 public
  { Déclarations publiques}
 end;

var
 Form1: TForm1;
 fclient : file of client;
 unclient : client;
 numero, n, i : longint;

implementation

uses gestlocalite;

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
  assignfile(fclient,'client.dat');
  {$i-}
  reset(fclient);
  {$i+}
  if ioresult <> 0 then
     begin
       rewrite(fclient);
       closefile(fclient);
       reset(fclient);
     end;
  numero := filesize(fclient);
  eca.text := '0';
  listclient.sorted := true;                                               Affichage de la liste triée
  form1.activecontrol := enom;
end;

procedure TForm1.FormClose(Sender : TObject; var Action : TCloseAction);
begin
  closefile(fclient);
  application.terminate;
end;




Eric.Brasseur@village.uunet.be                                                                           68
I.E.P.S.C.F. Marche en Famenne                                          Langage orienté gestion ( partie 1)


procedure TForm1.BquitterClick(Sender: TObject);
begin
  closefile(fclient);
  application.terminate;
end;

procedure TForm1.BlisterClick(Sender: TObject);
begin
  listclient.clear;
  n := 0;
  while (n < filesize(fclient)) do
    begin
      seek(fclient, n );
      read(fclient, unclient);
      if unclient.code[1] <> 'E' then
                                                                                   Test si effacé ou non
         begin
           listclient.items.add(unclient.nom + ' ' + unclient.prenom + ' ' +
                      unclient.adresse + ' ' + unclient.Cpostal + ' ' +
                      unclient.Localit + ' ' + unclient.Pays + ' ' +
                      inttostr(unclient.ca) + ' ' + unclient.code);
         end;
      n := n + 1;
    end;
end;

procedure TForm1.BnouveauClick(Sender: TObject);
begin
  ecode.text := '';
  enom.text := '';
  eprenom.text := '';
  eadresse.text := '';
  ecp.text := '';
  elocalite.text := '';
  epays.text := '';
  eca.text := '0';
  benregistrer.enabled := true;
  form1.activecontrol := enom;
end;

procedure TForm1.BrechercherClick(Sender: TObject);
var
 longueur, i : integer;
 test, trouve : boolean;
begin
 listclient.clear;
 n := 0;
 trouve := false;
 while (n < filesize(fclient)) do
   begin                                                       Test si effacé ou non
     seek(fclient, n );
     read(fclient, unclient);
     longueur := length(enom.text);
     test := true;
     i := 1;
     while (i <= longueur) do
        begin
          if(majusc(unclient.Nom[i]) <> majusc(enom.text[i])) or (unclient.code[i] = 'E' )
             then test := false;
          i := i + 1;
        end;



Eric.Brasseur@village.uunet.be                                                                                69
I.E.P.S.C.F. Marche en Famenne                                             Langage orienté gestion ( partie 1)


      if test = true then
         begin
          listclient.items.add(unclient.nom + ' ' + unclient.prenom + ' ' +
                        unclient.adresse + ' ' + unclient.Cpostal + ' ' +
                        unclient.Localit + ' ' + unclient.Pays + ' ' +
                        inttostr(unclient.ca) + ' ' + unclient.code );
          trouve := true;
         end;
      n := n + 1;
    end;
  if(trouve = false) then messagedlg('Aucun enregistrement ne correspond.', mterror,[mbok],0);
end;

procedure TForm1.ListclientClick(Sender: TObject);
var
  i : integer;
  test : boolean;
begin
  benregistrer.enabled := false;
  i := listclient.itemindex;
  ecode.text := copy(listclient.items[i],length(listclient.items[i]) - 5,6);
  n := 0;
  test := true;
  while (n < filesize(fclient)) and (test = true) do
     begin
       seek(fclient,n);
       read(fclient,unclient);
       n := n + 1;
       if (unclient.code = ecode.text) then
          begin
            ecode.text := unclient.code;
            enom.text := unclient.nom;
            eprenom.text := unclient.prenom;
            eadresse.text := unclient.adresse;
            ecp.text := unclient.Cpostal;
            elocalite.text := unclient.Localit;
            epays.text := unclient.Pays;
            eca.text := inttostr(unclient.ca);
            test := false;
          end;
     end;
end;

procedure TForm1.BenregistrerClick(Sender: TObject);
var
 longueur : integer;
begin
 if(messagedlg('Souhaitez-vous enregistrer la fiche de ce client ?', mtconfirmation,
     [mbok,mbcancel],0) = mrok)
    then begin
      if(enom.text = '') or (eprenom.text = '')
        then messagedlg('Fiche mal remplie ! ', mterror,[mbok],0)
        else
          begin
            unclient.code := inttostr(numero);
            longueur := length(unclient.code);
            case longueur of
              1 : unclient.code := 'C0000' + inttostr(numero);
              2 : unclient.code := 'C000' + inttostr(numero);
              3 : unclient.code := 'C00' + inttostr(numero);



Eric.Brasseur@village.uunet.be                                                                                   70
I.E.P.S.C.F. Marche en Famenne                                           Langage orienté gestion ( partie 1)


              4 : unclient.code := 'C0' + inttostr(numero);
              5 : unclient.code := 'C' + inttostr(numero);
            end;
            unclient.nom := enom.text;
            unclient.prenom := eprenom.text;
            unclient.adresse := eadresse.text;
            unclient.cpostal := ecp.text;
            unclient.localit := elocalite.text;
            unclient.Pays := epays.Text;
            try
             unclient.CA := strtoint(eca.text);
            except
             on E : Econverterror do unclient.CA := 0;
            end;
            seek(fclient, numero);
            write(fclient, unclient);
            lnum.caption := inttostr(numero + 1);
            numero := numero + 1;
            ecode.text := '';
            enom.text := '';
            eprenom.text := '';
            eadresse.text := '';
            ecp.text := '';
            elocalite.text := '';
            epays.text := '';
            eca.text := '0';
          end;
       end
    else begin
         messagedlg('Vous avez annulé l''enregistrement', mtwarning, [mbok],0);
       end;
  form1.activecontrol := enom;
end;

procedure Tform1.bgeslocclick(sender : TObject);
begin
  form2.binserer.visible := false;
                                                                                 Bouton insérer dans la deuxième
  form2.showmodal;
                                                                                 fenêtre visible ou non
end;

procedure Tform1.binslocclick(sender : TObject);
begin
  form2.binserer.visible := true;
  form2.showmodal;                                                               La fenêtre client n'est accessible
end;                                                                             que si la fenêtre localité est
                                                                                 fermée
procedure TForm1.BmodifierClick(Sender: TObject);
var
 n : integer;
begin
 n := filepos(fclient);
 if(enom.text = '') or (eprenom.text = '') or (n <= 0) or (n > filesize(fclient))
    then messagedlg('Fiche mal remplie ! ', mterror,[mbok],0)
    else
      begin
                                                                                 On ne peut modifier que si les
           unclient.nom := enom.text;
                                                                                 zones sont remplies et si on se
           unclient.prenom := eprenom.text;
                                                                                 trouve bien dans le fichier
           unclient.adresse := eadresse.text;
           unclient.cpostal := ecp.text;
           unclient.localit := elocalite.text;



Eric.Brasseur@village.uunet.be                                                                                     71
I.E.P.S.C.F. Marche en Famenne                                      Langage orienté gestion ( partie 1)


              unclient.Pays := epays.Text;                                 Routine de conversion des
              try                                                          strings en integers
               unclient.CA := strtoint(eca.text);
              except
               on E : Econverterror do unclient.CA := 0;
              end;
              seek(fclient, n - 1);
              write(fclient, unclient);
       end;
end;

procedure TForm1.BsupprimerClick(Sender: TObject);
var
 n : integer;
begin
 n := filepos(fclient);
 if(messagedlg('Confirmez la suppression de ce client ', mtconfirmation,
      [mbok,mbcancel],0) = mrok) and (n > 0)and (n <= filesize(fclient)) then
   begin
     unclient.code[1] := 'E';                                                   Je place un E pour signaler
     seek(fclient, n - 1);                                                      que l'enregistrement est
     write(fclient,unclient);                                                   effacé
   end;
end;
end.


unit gestlocalite;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 StdCtrls, Buttons;

type
 localite = record
   codepos : string[6];
   ville : string[20];
   pays : string[15];
 end;
 TForm2 = class(TForm)
  Comborecherche: TComboBox;
  Label1: TLabel;
  Label2: TLabel;
  Label3: TLabel;
  Label4: TLabel;
  Ecodpos: TEdit;
  Elocal: TEdit;
  Epa: TEdit;
  Listlocal: TListBox;
  Benregistrer: TButton;
  BQuitter: TButton;
  Binitialiser: TButton;
  Brechercher: TButton;
  BLister: TButton;
  Binserer: TBitBtn;
  procedure FormCreate(Sender: TObject);
  procedure ComborechercheChange(Sender: TObject);
  procedure BinsererClick(Sender: TObject);



Eric.Brasseur@village.uunet.be                                                                            72
I.E.P.S.C.F. Marche en Famenne                                         Langage orienté gestion ( partie 1)


  procedure BenregistrerClick(Sender: TObject);
  procedure BListerClick(Sender: TObject);
  procedure BrechercherClick(Sender: TObject);
  procedure BQuitterClick(Sender: TObject);
  procedure BinitialiserClick(Sender: TObject);
 private
  { Déclarations privées}
 public
  { Déclarations publiques}
 end;

var
 Form2: TForm2;
 flocalite : file of localite;
 unelocalite : localite;
 numero : longint;

implementation

uses ficheclient;
{$R *.DFM}

procedure TForm2.FormCreate(Sender: TObject);
var
 n : integer;
begin
  assignfile(flocalite,'localite.dat');
  {$i-}
   reset(flocalite);
  {$i+}
                                                       Je remplis mon combobox
  if ioresult <> 0 then
     begin
      rewrite(flocalite);
      closefile(flocalite);
      reset(flocalite);
     end;
  comborecherche.sorted := true;
  n := 0;
  while (n < filesize(flocalite)) do
    begin
      seek(flocalite,n);
      read(flocalite,unelocalite);
      comborecherche.items.add(unelocalite.ville + ' (' + unelocalite.pays[1]
       + unelocalite.pays[2] + ')');
      n := n + 1;
    end;
  numero := filesize(flocalite);
end;

procedure TForm2.ComborechercheChange(Sender: TObject);
var
 n : integer;
begin
 n := 0;
 while (n < filesize(flocalite)) do
  begin
    seek(flocalite,n);
    read(flocalite,unelocalite);
    if (comborecherche.text = unelocalite.ville + ' (' + unelocalite.pays[1]
       + unelocalite.pays[2] + ')') then



Eric.Brasseur@village.uunet.be                                                                               73
I.E.P.S.C.F. Marche en Famenne                                            Langage orienté gestion ( partie 1)


        begin
          ecodpos.text := unelocalite.codepos;
          elocal.text := unelocalite.ville;
          epa.text := unelocalite.pays;
        end;
    n := n + 1;
  end;
end;

procedure TForm2.BinsererClick(Sender: TObject);
begin
  if (ecodpos.text <> '') and (elocal.text <> '') and (epa.text <> '')
    then begin
        form1.ecp.text := ecodpos.text;                                              J'insère dans la
        form1.Elocalite.text := elocal.text;                                         fenêtre des clients si
        form1.Epays.text := epa.text[1] + epa.text[2];                               mes zones ne sont
       end                                                                           pas vides.
    else messagedlg('Sélection impossible.',mtwarning,[mbok],0);
end;

procedure TForm2.BenregistrerClick(Sender: TObject);
var
 trouve : boolean;
 n : integer;
begin
 if (ecodpos.text = '') or (elocal.text = '') or (epa.text = '')
   then messagedlg('Données incomplètes.',mterror,[mbok],0)
   else
    begin
      trouve := false;
      n := 0;
      while(n < filesize(flocalite)) and (trouve = false ) do
         begin
           seek(flocalite,n);
           read(flocalite,unelocalite);
           if (unelocalite.codepos = ecodpos.text) then trouve := true;
           n := n + 1;
         end;
      if (trouve = false)
        then
         begin
           numero := filesize(flocalite);
           unelocalite.codepos := ecodpos.text;
           unelocalite.ville := elocal.text;
           unelocalite.pays := epa.text;
           seek(flocalite,numero);
           write(flocalite,unelocalite);
           numero := numero + 1;
           ecodpos.text := '';
           elocal.text := '';
           epa.text := '';
         end
        else showmessage('La localité existe déjà');
    end;
 n := 0;
 comborecherche.clear;
 while(n < filesize(flocalite)) do
   begin
    seek(flocalite,n);
    read(flocalite,unelocalite);



Eric.Brasseur@village.uunet.be                                                                                  74
I.E.P.S.C.F. Marche en Famenne                                             Langage orienté gestion ( partie 1)


    comborecherche.items.add(unelocalite.ville + ' (' + unelocalite.pays[1]
       + unelocalite.pays[2] + ')');
    n := n + 1;
  end;
end;

procedure TForm2.BListerClick(Sender: TObject);
var
 n : integer;
begin
 listlocal.clear;
 n := 0;
 while (n < filesize(flocalite)) do
    begin
      seek(flocalite,n);
      read(flocalite,unelocalite);
      listlocal.items.add( unelocalite.codepos + ' ' + unelocalite.ville + ' ' +
        unelocalite.pays);
      n := n + 1;
    end;
end;

procedure TForm2.BrechercherClick(Sender: TObject);
var
 longueur,i,n : integer;
 test, trouve : boolean;
                                                                                     Recherche par code postal
 cherche : string[6];
begin
 trouve := false;
 cherche := '';
 listlocal.Clear;
 comborecherche.text := '';
 cherche := inputbox('Saisie de code', 'Veuillez introduire un code postal ( max 6 car ) : ','');
 if (cherche <> '') then
    begin
      n := 0;
      listlocal.clear;
      while(n < filesize(flocalite)) do
        begin
           seek(flocalite,n);
           read(flocalite,unelocalite);
           longueur := length(cherche);
           test := true;
           i := 1;
           while (i <= longueur) do
             begin
               if(unelocalite.codepos[i] <> cherche[i]) then test := false;
               i := i + 1;
             end;
           if (test = true ) then
              begin
                listlocal.items.add( unelocalite.codepos + ' ' + unelocalite.ville +
                  ' ' + unelocalite.pays);
                trouve := true;
              end;
           n := n + 1;
        end;
    end
    else
     begin



Eric.Brasseur@village.uunet.be                                                                                   75
I.E.P.S.C.F. Marche en Famenne                                   Langage orienté gestion ( partie 1)


      messagedlg('Recherche impossible', mterror,[mbok],0);
      ecodpos.text := '';
      elocal.text := '';
      epa.text := '';
    end;
  if (trouve = false ) then
    begin
      messagedlg('Aucune fiche trouvée',mterror,[mbok],0);
      ecodpos.text := '';
      elocal.text := '';
      epa.text := '';
    end;
end;

procedure TForm2.BQuitterClick(Sender: TObject);
begin
  form2.Close;
end;

procedure TForm2.BinitialiserClick(Sender: TObject);
begin
  ecodpos.text := '';
  elocal.text := '';
  epa.text := '';
  form2.activecontrol := ecodpos;
end;
end.


unit personnelle;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 StdCtrls;

function majusc(cara : string) : string;

implementation

function majusc(cara : string) : string;
var
caract : char;
resul : char;
begin
caract := char(cara[1]);
 case caract of
   'a'..'z'         : resul := upcase(caract);
   'é','è','ê','ë'    : resul := 'E';
   'ù','ü','û'        : resul := 'U';
   'à','â','ä'       : resul := 'A';
   'ô','ö'          : resul := 'O';
   'î','ï'         : resul := 'I';
   'ç'             : resul := 'C'
   else               resul := caract;
 end;
result := string(resul);
end;
end.



Eric.Brasseur@village.uunet.be                                                                         76
I.E.P.S.C.F. Marche en Famenne                                            Langage orienté gestion ( partie 1)


EXERCICE 601.
Créez une application qui travaille avec trois fichiers.

Client.dat dont la structure est la suivante :

Code ( string 8 ) et respectant la forme C*******
Nom ( string 25 )
Prénom ( string 20 )
Adresse ( string 35 )
Cpostal ( string 6 )
Localité ( string 25 )
Pays ( string 20 )
TVA ( string 11 )
Sexe ( string 1 ) et dont la valeur est F, M ou S
Remise ( entier )

Stock.dat dont la structure est la suivante :

Code ( string 10 ) et respectant la forme S*********
Libellé ( string 25 )
Famille ( string 11 )
PUHTVA ( réel )
Quantité ( réel )
Remise ( entier )

Localite.dat dont la structure est

Code ( string 10 ) et respectant la forme L*********
Ville ( string 25 )
CP ( string 6 )
Pays ( string 20 ).

Ces fichiers doivent permettre de remplir un écran représentant une facture ( je ne vous demande pas de
sauvegarder ces informations dans un fichier ). Sur la facture, on trouve les renseignements client, les lignes de
facture qui sont des articles du stock avec les mentions de prix unitaire, de remise, de prix net hors taxe. En fin
de facture, le total hors TVA, la TVA ( un seul taux : 21 %) et le montant TVA comprise.

Il faut pouvoir ajouter, modifier, chercher dans chaque fichier, supprimer des records dans le fichier client et le
fichier stock.

Les possibilités de recherches supplémentaires sont les bienvenues.

Dans chaque fichier, le code est unique et généré par le système. Chaque record supprimé aura son code qui
commencera par E suivi de son numéro.




Eric.Brasseur@village.uunet.be                                                                                        77
I.E.P.S.C.F. Marche en Famenne                                             Langage orienté gestion ( partie 1)


7. LES RECHNIQUES DE TRI, LES FUSIONS, LES TECHNIQUES DE
RECHERCHE.
Le tri ( sort en anglais ) consiste à placer les éléments d'un tableau dans un autre ordre que l'ordre de départ.
Nous trierons des fichiers en plaçant le contenu des champs à trier dans un ( ou des ) tableau(x). Il existe un
grand nombre de méthodes de tri. Nous en étudierons trois élémentaires qui conviennent bien pour des petits
nombres d'enregistrements et une méthode très rapide pour les grands tableaux mais dont l'algorithme est plus
compliqué.
La fusion ( merge en anglais ) consiste à regrouper des tableaux préalablement triés sur le même champ pour
refaire un fichier unique. En effet, certains fichiers sont trop gros que pour tenir entièrement dans un seul
tableau. On segmente le fichier en un certain nombre de tableau qu'on trie chacun de leur côté puis on fusionne
ces différents tableaux pour retrouver un fichier trié.
Nous verrons également comment trier sur plusieurs champs avec un tri primaire et des tris secondaires.
Le but final est de créer des routines qui pourront servir à la manipulation des fichiers. Nous travaillerons
toujours dans l'ordre croissant et sur des nombres entiers. Pour trier par ordre décroissant, il suffit de retourner
les signes. La méthode est également valable pour les chaînes de caractères.

7.1. Tri par extraction simple.
Ce tri consiste à se promener dans le tableau, à trouver le plus petit élément par balayage et à le permuter avec le
premier du tableau puis à recommencer pour le second élément du tableau et ainsi de suite. Exemple :

3        9        2        7        11        6        2        8

2        9        3        7        11        6        2        8
2        2        3        7        11        6        9        8
2        2        3        7        11        6        9        8
2        2        3        6        11        7        9        8
2        2        3        6        7         11       9        8
2        2        3        6        7         8        9        11
2        2        3        6        7         8        9        11

Une routine de permutation d'éléments peut être écrite pour être toujours utilisée.Vous la trouverez dans l'unité
biblio. Prévoyez un tableau suffisamment grand que pour pouvoir y inscrire tous les éléments. Pour vérifier
votre algorithme, affichez à l'écran toutes les étapes. ( par exemple dans un stringrid ou un label avec saut à la
ligne pour chaque étape ).




Eric.Brasseur@village.uunet.be                                                                                       78
I.E.P.S.C.F. Marche en Famenne                                           Langage orienté gestion ( partie 1)


Voici le programme complet :

unit fentri;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 StdCtrls, Grids, biblio;

type
 TForm1 = class(TForm)
  Sttri: TStringGrid;
  Bsaisir: TButton;
  Btrier: TButton;
  Bquitter: TButton;
  procedure BquitterClick(Sender: TObject);
  procedure FormClose(Sender: TObject; var Action: TCloseAction);
  procedure FormCreate(Sender: TObject);
  procedure BsaisirClick(Sender: TObject);
  procedure BtrierClick(Sender: TObject);
 private
 public
 end;

var
 Form1: TForm1;
 atrier : array[1..10] of integer;
 nbatrier : integer;

implementation

{$R *.DFM}

procedure TForm1.BquitterClick(Sender: TObject);
begin
  application.terminate;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  application.terminate;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin                                                                    Le stringgrid n'est pas visible au
  sttri.visible := false;                                                départ
end;

procedure TForm1.BsaisirClick(Sender: TObject);
var
 i : integer;
begin
 repeat
    try
      nbatrier := strtoint(inputbox('','Nombre d''items à trier : ','0'));        Saisie avec vérification.
    except
     on E: Econverterror do showmessage('Du numérique S.V.P.');
    end;
 until (nbatrier < 11) and (nbatrier > 0);



Eric.Brasseur@village.uunet.be                                                                                 79
I.E.P.S.C.F. Marche en Famenne                                                  Langage orienté gestion ( partie 1)


  for i := 1 to nbatrier do
    begin
     try
         atrier[i] := strtoint(inputbox('','Item n°' + inttostr(i) + ' : ','0'));        Saisie avec vérification
     except
         on E: Econverterror do showmessage('Du numérique S.V.P.');
     end;
    end;
  sttri.visible := true;                                                                 Remplir le titre avec les
  sttri.colcount := nbatrier + 1;                                                        valeurs de départ.
  sttri.RowCount := 1;
  sttri.cells[0,0] := 'LISTE';
  for i := 1 to nbatrier do sttri.cells[i,0] := inttostr(atrier[i]);
end;

procedure TForm1.BtrierClick(Sender: TObject);
var
 i, j, k, petit : integer;                                                               Je cherche le plus petit
begin                                                                                    dans la série tout en
 for i := 1 to (nbatrier - 1) do                                                         rétrécissant à chaque
     begin                                                                               étape la zone de
       petit := atrier[i];                                                               recherche et je conserve
       k := i;                                                                           sa position dans k
       for j := (i + 1) to nbatrier do
          begin
            if atrier[j] < petit then
               begin
                  petit := atrier[j];
                  k := j;
               end;
          end;
       if atrier[i] > atrier[k] then
           begin
                                                                                       Si le nombre trouvé est
               permut(atrier[i], atrier[k]);
                                                                                       plus plus petit que celui
               sttri.RowCount := sttri.rowcount + 1;
                                                                                       de gauche, je permute et
               sttri.fixedrows := 1;
                                                                                       j'ajoute une nouvelle
               sttri.cells[0,i] := 'ETAPE' + inttostr(i);
                                                                                       ligne à ma grille avec la
               for j := 1 to nbatrier do sttri.cells[j,i] := inttostr(atrier[j]);
                                                                                       permutation écrite
           end;
     end;
end;

end.


Pour les deux prochaines méthodes de tri, je vais garder le même programme et ne changer que la procédure de
tri.

7.2. Tri par permutation simple.

On parcourt le tableau en comparant un élément avec le suivant et on permute si l'ordre demandé n'est pas
respecté. On va jusqu'au dernier qui devient le plus grand puis on recommence du premier à l'avant-dernier.

3        9         2         7         11        6         2         8
3        2         9         7         11        6         2         8
3        2         7         9         11        6         2         8
3        2         7         9         6         11        2         8
3        2         7         9         6         2         11        8
3        2         7         9         6         2         8         11
2        3         7         9         6         2         8         11



Eric.Brasseur@village.uunet.be                                                                                        80
I.E.P.S.C.F. Marche en Famenne                        Langage orienté gestion ( partie 1)


2      3       7      6          9    2      8   11
2      3       7      6          2    9      8   11
2      3       7      6          2    8      9   11
2      3       6      7          2    8      9   11
2      3       6      2          7    8      9   11
2      3       2      6          7    8      9   11
2      2       3      6          7    8      9   11




procedure TForm1.BtrierClick(Sender: TObject);
var
 i, j, k, etape: integer;
 perm : boolean;
begin
 i := nbatrier;
 etape := 0;
 repeat
    perm := FALSE;
    for j := 1 to i - 1 do
       begin
         if atrier[j] > atrier[j + 1] then                           Etape sert à numéroter
            begin                                                    les permutations et à me
             etape := etape + 1;                                     positionner dans le
                                                                     stringgrig

Eric.Brasseur@village.uunet.be                                                              81
I.E.P.S.C.F. Marche en Famenne                                            Langage orienté gestion ( partie 1)


            permut(atrier[j],atrier[j + 1]);
            perm := TRUE;
            sttri.RowCount := sttri.rowcount + 1;
            sttri.fixedrows := 1;
            sttri.cells[0,etape] := 'ETAPE' + inttostr(etape);
            for k := 1 to nbatrier do sttri.cells[k,etape] := inttostr(atrier[k]);
          end;
     end;
  i := i - 1;                                                                            J'arrête de chercher quand
 until perm = FALSE;                                                                     je n'ai rien permuté
end;                                                                                     pendant un tour
7.3. Tri par permutation répétée.

Le premier élément est comparé au second et s'il le faut : permutation. Puis comparaison avec le troisième
jusqu'à la fin. Ensuite on recommence à partir du second et ainsi de suite.

3        9        2        7        11       6        2         8

2        9        3        7        11       6        2         8
2        3        9        7        11       6        2         8
2        2        9        7        11       6        3         8
2        2        7        9        11       6        3         8
2        2        6        9        11       7        3         8
2        2        3        9        11       7        6         8
2        2        3        7        11       9        6         8
2        2        3        6        11       9        7         8
2        2        3        6        9        11       7         8
2        2        3        6        7        11       9         8
2        2        3        6        7        9        11        8
2        2        3        6        7        8        11        9
2        2        3        6        7        8        9         11




procedure TForm1.BtrierClick(Sender: TObject);
var
 i, j, k : integer;
begin



Eric.Brasseur@village.uunet.be                                                                                  82
I.E.P.S.C.F. Marche en Famenne                                              Langage orienté gestion ( partie 1)


 for i := 1 to (nbatrier - 1) do
   begin
      for j := i + 1 to nbatrier do
        begin
          if atrier[i] > atrier[j] then
             begin
               permut(atrier[i],atrier[j]);
             end;
        end;
      sttri.RowCount := sttri.rowcount + 1;
      sttri.fixedrows := 1;
      sttri.cells[0,i] := 'ETAPE' + inttostr(i);
      for k := 1 to nbatrier do sttri.cells[k,i] := inttostr(atrier[k]);
   end;
end;
                         Voici le code de la librairie biblio qui contient la procédure permut :

unit biblio;
interface
procedure permut(var x : integer; var y : integer);
implementation
procedure permut(var x : integer; var y : integer);                              Passage de paramètres par adresse
var
 z : integer;
begin
 z := x;
 x := y;
 y := z;
end;
end.

7.4 . Le quicksort.




                                              On voit ici les segments de tri



Cette méthode de tri rapide a été écrite par C. A. R. Hoare. Elle est basée sur la segmentation. Il faut choisir une
valeur pivot ( en général, le milieu du tableau ). On réorganise ensuite les deux parties du tableau de telle sorte
que : tab[i] < tab[x] si i < x et tab[j] > tab[x] si j > x. En d'autres termes, on déplace vers le haut du tableau les
valeurs supérieures au pivot présentes dans la partie basse et complémentairement, on déplace vers le bas du
tableau les valeurs inférieures au pivot présentes dans la partie haute. Deux compteurs ( i qui s'incrémente


Eric.Brasseur@village.uunet.be                                                                                     83
I.E.P.S.C.F. Marche en Famenne                                           Langage orienté gestion ( partie 1)


jusque x pour le bas et j qui se décrémente jusque x pour le haut ) sont utilisés pour indexer. On segmente
ensuite en deux la partie haute et la partie basse et ainsi de suite. Nous allons utiliser la récursivité : une
procédure s'appelle elle-même. Attention : l'appel à la procédure de tri comporte trois paramètres : le début et la
fin du segment à trier et le nom du tableau à trier.

unit fentri;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 StdCtrls, Grids, biblio;
type

 TForm1 = class(TForm)
  Sttri: TStringGrid;
  Bsaisir: TButton;
  Btrier: TButton;
  Bquitter: TButton;
  procedure BquitterClick(Sender: TObject);
  procedure FormClose(Sender: TObject; var Action: TCloseAction);
  procedure FormCreate(Sender: TObject);
  procedure BsaisirClick(Sender: TObject);
  procedure BtrierClick(Sender: TObject);

 private
  { Déclarations privées}
 public
  { Déclarations publiques}
 end;

var
 Form1: TForm1;
 atrier : taba;
 nbatrier : integer;

implementation

{$R *.DFM}

procedure TForm1.BquitterClick(Sender: TObject);
begin
  application.terminate;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  application.terminate;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  sttri.visible := false;
end;

procedure TForm1.BsaisirClick(Sender: TObject);
var
 i : integer;
begin
 repeat



Eric.Brasseur@village.uunet.be                                                                                   84
I.E.P.S.C.F. Marche en Famenne                                            Langage orienté gestion ( partie 1)


     try
       nbatrier := strtoint(inputbox('','Nombre d''items à trier : ','0'));
     except
      on E: Econverterror do showmessage('Du numérique S.V.P.');
     end;
  until (nbatrier < 11) and (nbatrier > 0);
  for i := 1 to nbatrier do
     begin
      try
         atrier[i] := strtoint(inputbox('','Item n°' + inttostr(i) + ' : ','0'));
       except
         on E: Econverterror do showmessage('Du numérique S.V.P.');
       end;
     end;
  sttri.visible := true;
  sttri.colcount := nbatrier + 1;
  sttri.RowCount := 1;
  sttri.cells[0,0] := 'LISTE';
  for i := 1 to nbatrier do sttri.cells[i,0] := inttostr(atrier[i]);
end;
                                                                         Appel à la procédure de tri avec 3 paramètres
procedure TForm1.BtrierClick(Sender: TObject);                           : la position du premier et du dernier nombre
var                                                                      dans le tableau et le nom de ce tableau.
  i : integer;
begin
  sttri.visible := true;
  quicksort(1, nbatrier, atrier );                                       A la fin, je dois afficher le résultat trié.
  sttri.RowCount := sttri.rowcount + 1;
  sttri.cells[0,sttri.rowcount-1] := 'FIN';
  for i := 1 to nbatrier do sttri.cells[i,sttri.rowcount-1] := inttostr(atrier[i]);
end;

end.
                                               La librairie associée :

unit biblio;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 StdCtrls, Grids;
type
 taba = array[1..10] of integer;

procedure permut(var x : integer; var y : integer);
procedure quicksort(debut : integer; compt : integer; var atrier : taba);

implementation
uses
  fentri;

procedure permut(var x : integer; var y : integer);
var
 z : integer;
begin
 z := x;8
 x := y;
 y := z;
end;



Eric.Brasseur@village.uunet.be                                                                                     85
I.E.P.S.C.F. Marche en Famenne                                                Langage orienté gestion ( partie 1)



procedure quicksort(debut : integer; compt : integer; var atrier : taba);
var
 i, j, x, k : integer;
begin                                                  Recherche du pivot ( valeur centrale )
 i := debut;
 j := compt;
 x := atrier[(debut + compt) div 2];                   Tant que le nombre est inférieur dans
 repeat                                                la partie basse ou supérieur dans la
    while atrier[i] < x do                             partie haute, je continue à avancer.
       i := i + 1;                                     Dans le cas contraire, je procède à une
    while atrier[j] > x do                             permutation si i <= j. Je répète cette
       j := j - 1;                                     opération jusqu'à ce que i > j.
    if i <= j then
       begin
          permut (atrier[i],atrier[j]);
          i := i + 1;                                  Appels récursifs sur une partie du
          j := j - 1;                                  tableau ( la moitié supérieure ou
      end;                                             inférieure du segment en cours )
 until i > j;
 form1.sttri.RowCount := form1.sttri.rowcount + 1;
 form1.sttri.fixedrows := 1;
 form1.sttri.cells[0,form1.sttri.rowcount-1] := 'ETAPE' + inttostr(form1.sttri.rowcount-1);
 for k := debut to compt do form1.sttri.cells[k,form1.sttri.rowcount-1] := inttostr(atrier[k]);
 if debut < j then quicksort(debut, j, atrier);
 if compt > i then quicksort(i, compt, atrier);
end;
end.

7.5. Le tri à plusieurs critères.

Nous allons créer un tableau à deux dimensions. Chaque ligne va représenter un record comprenant plusieurs
champs.

Nous permettrons le tri monocritère sur plusieurs champs puis nous examinerons les résultats obtenus. Ce
programme sera conçu de la façon suivante :

             remplir le tableau
             implémenter une méthode de tri et l'adapter à tous les champs
             effectuer des tris successifs

La difficulté principale réside dans le fait que nous allons comparer des strings ; il faudra donc comparer des
niveaux comparables : il faudra donc concevoir une fonction qui transformera un string en string majuscule mais
uniquement au moment de la comparaison.

Je conseille de sauver le tableau dans un fichier pour ne pas devoir le réencoder à chaque nouvel essai.


Pour effectuer un tri sur plusieurs critères, il faut d'abord trier sur le critère secondaire puis ensuite sur le critère
primaire. Je n'ai pas implémenté cette option. Je vous conseille de la tester.




Eric.Brasseur@village.uunet.be                                                                                          86
I.E.P.S.C.F. Marche en Famenne                                           Langage orienté gestion ( partie 1)




J'ai remplacé les titres des colonnes par des boutons qui permettent le tri sur la colonne concernée. Voici le
source :

program trimulti;
uses
 Forms,
 principal in 'principal.pas' {Form1};

{$R *.RES}

begin
 Application.Initialize;
 Application.CreateForm(TForm1, Form1);
 Application.Run;
end.

unit principal;
interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 Grids, StdCtrls;

type
 eleve = record
    Nom       : string[15];
    Prenom : string[15];                                              Déclaration de type pour mon
    Adresse : string[30];                                             fichier et mon tableau à trier
    Cp      : string[5];
    Localite : string[15];
    num      : longint;                                               Tableau qui servira à mon tri
 End;
  tabatrier = array[0..4999] of eleve;


Eric.Brasseur@village.uunet.be                                                                                   87
I.E.P.S.C.F. Marche en Famenne                                        Langage orienté gestion ( partie 1)


 TForm1 = class(TForm)
  STRgrille: TStringGrid;
  enom: TEdit;
  eprenom: TEdit;
  eadresse: TEdit;
  ecodepostal: TEdit;
  Elocalite: TEdit;
  Label1: TLabel;
  Label2: TLabel;
  Label3: TLabel;
  Label4: TLabel;
  Label5: TLabel;
  Bajouter: TButton;                                                      Trois procédures ou
  Btrinom: TButton;                                                       fonctions que j'ai placées
  Btriprenom: TButton;                                                    directement dans mon unité
  btrilocalite: TButton;
  Bquitter: TButton;
  Btricp: TButton;
  bnouveau: TButton;
  Btriadresse: TButton;
  procedure FormCreate(Sender: TObject);
  procedure FormClose(Sender: TObject; var Action: TCloseAction);
  procedure BquitterClick(Sender: TObject);
  procedure bnouveauClick(Sender: TObject);
  procedure BajouterClick(Sender: TObject);
  procedure quicksort(debut : integer; compt : integer; posit : integer; var atrier : tabatrier; bool :
boolean);
  function maj(chaine : string) : string;
  procedure permut(var x : eleve; var y : eleve);
  procedure BtrinomClick(Sender: TObject);
  procedure BtriprenomClick(Sender: TObject);
  procedure BtriadresseClick(Sender: TObject);
  procedure BtricpClick(Sender: TObject);
  procedure btrilocaliteClick(Sender: TObject);
 procedure Tform1.OnDrawCell(Sender: TObject; ACol, ARow: Longint; rect : trect; State:
TGridDrawState);

 private
  { Déclarations privées}
 public                                                                  Booleéns qui me
  { Déclarations publiques}                                              permettent de trier le
 end;                                                                    fichier en ascendant ou
                                                                         descendant
var
 Form1: TForm1;
 feleve : file of eleve;
 uneleve : eleve;
 numero : longint;
 atrier : tabatrier;
 ascendantnom, ascendantprenom, ascendantadresse, ascendantcp, ascendantlocalite : boolean;
implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject);
var
 i : longint;
begin
   btrinom.visible := false;
   btriprenom.visible := false;
   btricp.visible := false;
   btrilocalite.visible := false;



Eric.Brasseur@village.uunet.be                                                                              88
I.E.P.S.C.F. Marche en Famenne                               Langage orienté gestion ( partie 1)


  btriadresse.visible := false;
  assignfile(feleve,'eleve.dat');
  {$i-}
  reset(feleve);
  {$i+}
  if ioresult <> 0 then
     begin
       rewrite(feleve);
       closefile(feleve);
       reset(feleve);
     end;
  numero := filesize(feleve);
  strgrille.RowCount := numero;
  strgrille.visible := true;
  btrinom.visible := true;
  btriprenom.visible := true;
  btricp.visible := true;
  btrilocalite.visible := true;
  btriadresse.visible := true;
  if numero >=1 then
    begin
      for i := 0 to numero - 1 do
       begin
        seek(feleve,i);
        read(feleve, uneleve);
        strgrille.cells[0,i] := uneleve.nom;
        strgrille.cells[1,i] := uneleve.Prenom;                     Je remplis ma grille avec les
        strgrille.cells[2,i] := uneleve.Adresse;                    records du fichier
        strgrille.cells[3,i] := uneleve.Cp;
        strgrille.cells[4,i] := uneleve.Localite;
        atrier[i] := uneleve;                                       Je place le record dans le tableau
       end;
    end;
  form1.activecontrol := enom;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 closefile(feleve);
 application.terminate;
end;

procedure TForm1.BquitterClick(Sender: TObject);
begin
 closefile(feleve);
 application.terminate;
end;

procedure TForm1.bnouveauClick(Sender: TObject);
begin
  enom.text := '';
  eprenom.text := '';
  eadresse.text := '';
  elocalite.text := '';
  ecodepostal.Text := '';
  bajouter.enabled := true;
  form1.activecontrol := enom;
end;

procedure TForm1.BajouterClick(Sender: TObject);



Eric.Brasseur@village.uunet.be                                                                      89
I.E.P.S.C.F. Marche en Famenne                                        Langage orienté gestion ( partie 1)


begin
  if(messagedlg('Souhaitez-vous enregistrer la fiche de cet élève ?', mtconfirmation,
      [mbok,mbcancel],0) = mrok)
     then begin
       if(enom.text = '') or (eprenom.text = '')
          then messagedlg('Fiche mal remplie ! ', mterror,[mbok],0)
          else
            begin
              numero := filesize(feleve);
              uneleve.nom := enom.text;
              uneleve.prenom := eprenom.text;                                    J'ajoute le record dans le
              uneleve.adresse := eadresse.text;                                  fichier
              uneleve.cp      := ecodepostal.text;
              uneleve.localite := elocalite.text;
              uneleve.num := numero;
              seek(feleve, numero);
              write(feleve, uneleve);
              atrier[numero] := uneleve;
                                                                                 Dans le tableau
              bajouter.Enabled := false;
              strgrille.rowcount := numero + 1;
              strgrille.cells[0,numero] := enom.text;
              strgrille.cells[1,numero] := eprenom.text;
              strgrille.cells[2,numero] := eadresse.text;                        Dans la grille
              strgrille.cells[3,numero] := ecodepostal.text;
              strgrille.cells[4,numero] := elocalite.text;
            end;
         end
     else begin
           messagedlg('Vous avez annulé l''enregistrement', mtwarning, [mbok],0);
         end;
  form1.activecontrol := enom;
end;

function tform1.maj(chaine : string) : string;
var
caract : char;
i : integer;
begin
for i := 1 to length(chaine) do
  begin
    caract := char(chaine[i]);
    case caract of
     'a'..'z'         : chaine[i] := upcase(caract);
                                                                                La comparaison se fait sur
     'é','è','ê','ë'    : chaine[i] := 'E';
                                                                                des chaînes en majuscules
     'ù','ü','û'        : chaine[i] := 'U';
     'à','â','ä'       : chaine[i] := 'A';
     'ô','ö'          : chaine[i] := 'O';
     'î','ï'         : chaine[i] := 'I';
     'ç'             : chaine[i] := 'C'
     else               chaine[i] := caract;
    end;
  end;
result := chaine;
end;

procedure tform1.permut(var x : eleve; var y : eleve);
var
 z : eleve;
begin
 z := x;



Eric.Brasseur@village.uunet.be                                                                                90
I.E.P.S.C.F. Marche en Famenne                                           Langage orienté gestion ( partie 1)
                                            J'ai ajouté deux paramètres : posit qui me donnera la colonne sur
                                            laquelle le tri sera effectué et bool qui me donnera le sens du tri
 x := y;                                    précédent ( en réalité, il retourne une valeur qui peut ne pas
 y := z;                                    correspondre si le dernier tri a été effectué sur une autre colonne)
end;


procedure tform1.quicksort(debut : integer; compt : integer; posit : integer; var atrier : tabatrier; bool :
boolean);
var
 i, j: integer;
 x : string;
begin
 i := debut;
 j := compt;
 case posit of
   1 : x := maj(atrier[(debut + compt) div 2].nom);                           Le case teste la colonne
   2 : x := maj(atrier[(debut + compt) div 2].prenom);                        seur laquelle le tri est
   3 : x := maj(atrier[(debut + compt) div 2].adresse);                       effectué.
   4 : x := maj(atrier[(debut + compt) div 2].cp);
   5 : x := maj(atrier[(debut + compt) div 2].localite);
 end;
 repeat
    case posit of
     1 : begin
          if bool then
            begin
             while maj(atrier[i].nom) < x do i := i + 1;
             while maj(atrier[j].nom) > x do j := j - 1;                        Teste le sens du tri
            end                                                                 suivant le booléen
          else                                                                  passé.
            begin
             while maj(atrier[i].nom) > x do i := i + 1;
             while maj(atrier[j].nom) < x do j := j - 1;
            end;
         end;
     2 : begin
          if bool then
            begin
             while maj(atrier[i].prenom) < x do i := i + 1;
             while maj(atrier[j].prenom) > x do j := j - 1;
            end
          else
            begin
             while maj(atrier[i].prenom) > x do i := i + 1;
             while maj(atrier[j].prenom) < x do j := j - 1;
            end;
         end;
     3 : begin
          if bool then
            begin
             while maj(atrier[i].adresse) < x do i := i + 1;
             while maj(atrier[j].adresse) > x do j := j - 1;
            end
          else
            begin
             while maj(atrier[i].adresse) > x do i := i + 1;
             while maj(atrier[j].adresse) < x do j := j - 1;
            end;
         end;
     4 : begin
          if bool then



Eric.Brasseur@village.uunet.be                                                                                 91
I.E.P.S.C.F. Marche en Famenne                                   Langage orienté gestion ( partie 1)


             begin
              while maj(atrier[i].cp) < x do i := i + 1;
              while maj(atrier[j].cp) > x do j := j - 1;
             end
           else
             begin
              while maj(atrier[i].cp) > x do i := i + 1;
              while maj(atrier[j].cp) < x do j := j - 1;
             end;
         end;
      5 : begin
           if bool then
             begin
              while maj(atrier[i].localite) < x do i := i + 1;
              while maj(atrier[j].localite) > x do j := j - 1;
             end
           else
             begin
              while maj(atrier[i].localite) > x do i := i + 1;
              while maj(atrier[j].localite) < x do j := j - 1;
             end;
         end;
    end;
    if i <= j then
       begin
         permut (atrier[i],atrier[j]);
         i := i + 1;
         j := j - 1;
       end;
 until i > j;                                                             Appel récursif avec 5
 if debut < j then quicksort(debut, j, posit, atrier, bool);              paramètres
 if compt > i then quicksort(i, compt, posit, atrier, bool);
end;

procedure TForm1.BtrinomClick(Sender: TObject);
var
 i : integer;
begin
   numero := filesize(feleve);
   quicksort(0,numero - 1,1,atrier,ascendantnom);                         Je ferme le fichioer
   closefile(feleve);                                                     puis je le recrée vide
   rewrite(feleve);                                                       pour rééncoder tous
   for i := 0 to numero - 1 do                                            les records triés.
     begin
      seek(feleve,i);
      write(feleve,atrier[i]);
      strgrille.cells[0,i] := atrier[i].nom;
      strgrille.cells[1,i] := atrier[i].prenom;                           Je complète la grille.
      strgrille.cells[2,i] := atrier[i].adresse;
      strgrille.cells[3,i] := atrier[i].cp;
      strgrille.cells[4,i] := atrier[i].localite;
     end;
   ascendantnom := not(ascendantnom);
end;

procedure TForm1.BtriprenomClick(Sender: TObject);
var
 i : integer;
begin
   numero := filesize(feleve);



Eric.Brasseur@village.uunet.be                                                                         92
I.E.P.S.C.F. Marche en Famenne                          Langage orienté gestion ( partie 1)


  quicksort(0,numero - 1,2,atrier,ascendantprenom);
  closefile(feleve);
  rewrite(feleve);
  for i := 0 to numero - 1 do
   begin
     seek(feleve,i);
     write(feleve,atrier[i]);
     strgrille.cells[0,i] := atrier[i].nom;
     strgrille.cells[1,i] := atrier[i].prenom;
     strgrille.cells[2,i] := atrier[i].adresse;
     strgrille.cells[3,i] := atrier[i].cp;
     strgrille.cells[4,i] := atrier[i].localite;
   end;
  ascendantprenom := not(ascendantprenom);
end;

procedure TForm1.BtriadresseClick(Sender: TObject);
var
 i : integer;
begin
   numero := filesize(feleve);
   quicksort(0,numero - 1,3,atrier,ascendantadresse);
   closefile(feleve);
   rewrite(feleve);
   for i := 0 to numero - 1 do
     begin
      seek(feleve,i);
      write(feleve,atrier[i]);
      strgrille.cells[0,i] := atrier[i].nom;
      strgrille.cells[1,i] := atrier[i].prenom;
      strgrille.cells[2,i] := atrier[i].adresse;
      strgrille.cells[3,i] := atrier[i].cp;
      strgrille.cells[4,i] := atrier[i].localite;
     end;
   ascendantadresse := not(ascendantadresse);
end;

procedure TForm1.BtricpClick(Sender: TObject);
var
 i : integer;
begin
   numero := filesize(feleve);
   quicksort(0,numero - 1,4,atrier,ascendantcp);
   closefile(feleve);
   rewrite(feleve);
   for i := 0 to numero - 1 do
     begin
      seek(feleve,i);
      write(feleve,atrier[i]);
      strgrille.cells[0,i] := atrier[i].nom;
      strgrille.cells[1,i] := atrier[i].prenom;
      strgrille.cells[2,i] := atrier[i].adresse;
      strgrille.cells[3,i] := atrier[i].cp;
      strgrille.cells[4,i] := atrier[i].localite;
     end;
  ascendantcp := not(ascendantcp);
end;

procedure TForm1.btrilocaliteClick(Sender: TObject);
var



Eric.Brasseur@village.uunet.be                                                                93
I.E.P.S.C.F. Marche en Famenne                                             Langage orienté gestion ( partie 1)


 i : integer;
begin
   numero := filesize(feleve);
   quicksort(0,numero - 1,5,atrier,ascendantlocalite);
   closefile(feleve);
   rewrite(feleve);
   for i := 0 to numero - 1 do
     begin
      seek(feleve,i);
      write(feleve,atrier[i]);
      strgrille.cells[0,i] := atrier[i].nom;
      strgrille.cells[1,i] := atrier[i].prenom;
      strgrille.cells[2,i] := atrier[i].adresse;
      strgrille.cells[3,i] := atrier[i].cp;
      strgrille.cells[4,i] := atrier[i].localite;
     end;
   ascendantlocalite := not(ascendantlocalite);
end;

procedure Tform1.OnDrawCell(Sender: TObject; ACol, ARow: Longint; rect : trect; State:
TGridDrawState);
var                                                               Cette procédure de l'événement ondrawcell du
paire : integer;                                                  stringgrig permet de changer les couleurs de fond et
begin                                                             de texte des cellules. Ici, une ligne sur deux est de
  paire := arow mod 2;                                            couleur différente. On y trouve successivement les
  if paire = 0 then strgrille.canvas.brush.color := clScrollBar   couleurs, le remplissage puis le dessin de la grille.
               else strgrille.canvas.brush.color := clwhite;
  strgrille.Canvas.Font.color := clblack;
  strgrille.canvas.fillrect(rect);
  strgrille.canvas.textout(rect.left+2,rect.top+2,strgrille.CELLS[aCOL,aROW]);
end;

end.


Il conviendrait mieux de sauvegarder le fichier trié dans un autre fichier du même type. Ensuite, on ferme le
premier, on le supprime puis on change le nom du deuxième qui prend le nom du premier. De cette façon, on a
toujours une sauvegarde sur disque de notre fichier.

Ce programme fonctionne avec les quelques records encodés. Vous pouvez créer un programme générant des
records automatiquement de la façon suivante :


             créer un fichier avec un seul champ nom de la même longueur que dans notre fichier
             vous encodez environ 100 noms
             vous répétez l'opération avec les autres champs ( un fichier par champ )
             vous remplissez aléatoirement le fichier élève avec les champs issus des autres fichiers ( travaillez
              avec un random différent pour chaque champ )
             vous adaptez la taille du tableau (cette table est déclarée dans le programme ci-dessus)

Ce type de test permet

             de se rendre compte du temps nécessaire pour effectuer des tris
             de déterminer la taille limite d'un tableau en fonction du système dont vous disposez
             de déterminer la limite de la la pile pour les appels récursifs

Que faut-il faire si vous déopassez une limite lors d'un tri ?

             segmenter votre fichier en plusieurs fichiers du même type
             trier chacun de ces segments


Eric.Brasseur@village.uunet.be                                                                                    94
I.E.P.S.C.F. Marche en Famenne                                                Langage orienté gestion ( partie 1)


               fusionner vos segments pour en faire un fichier unique trié

Cette méthode porte le nom de SORT - MERGE ( tri Ŕ fusion ).

Un test effectué sur un fichier de grande taille permet de définir l'environnement matériel minimum pour que
votre logiciel tourne sans dépassement de capacité.

Vous devez en tenir compte pour l'installation du logiciel en situation réelle et éventuellement pour adapter le tri
à cette situation . ( tri en fin de journée, segmentation différente, …)

Voici un programme générant un fichier rapidement ( le nombre de records est demandé ).




unit fichcre;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 StdCtrls;

type
 eleve = record
    Nom       : string[15];
    Prenom : string[15];
    Adresse : string[30];
    Cp       : string[5];
    Localite : string[15];
    num      : longint;
 End;
 pnom = record
    nom      : string[15];
 end;
 pprenom = record
    prenom       : string[15];
 end;



Eric.Brasseur@village.uunet.be                                                                                      95
I.E.P.S.C.F. Marche en Famenne                 Langage orienté gestion ( partie 1)


 padresse = record
    adresse      : string[30];
 end;
 pcp = record
    cp     : string[5];
 end;
 plocalite = record
    localite     : string[15];
 end;
 tabnom = array[0..99] of pnom;
 tabadresse = array[0..99] of padresse;
 tabprenom = array[0..99] of pprenom;
 tabcp = array[0..99] of pcp;
 tablocalite = array[0..99] of plocalite;
 TForm1 = class(TForm)
  bquantite: TButton;
  Bnom: TButton;
  Bprenom: TButton;
  Badresse: TButton;
  Bcp: TButton;
  Blocalite: TButton;
  Bcreation: TButton;
  OK: TEdit;
  procedure FormCreate(Sender: TObject);
  procedure bquantiteClick(Sender: TObject);
  procedure BnomClick(Sender: TObject);
  procedure BprenomClick(Sender: TObject);
  procedure BadresseClick(Sender: TObject);
  procedure BlocaliteClick(Sender: TObject);
  procedure BcpClick(Sender: TObject);
  procedure BcreationClick(Sender: TObject);

 private
  { Déclarations privées}
 public
  { Déclarations publiques}
 end;

var
 Form1: TForm1;
 feleve : file of eleve;
 fnom : file of pnom;
 fprenom : file of pprenom;
 fadresse : file of padresse;
 fcp : file of pcp;
 flocalite : file of plocalite;
 anom : tabnom;
 aprenom : tabprenom;
 aadresse : tabadresse;
 acp : tabcp;
 alocalite : tablocalite;
 nbfiches : longint;
 unnom : pnom;
 unprenom : pprenom;
 unadresse : padresse;
 uncp : pcp;
 unlocalite : plocalite;
 uneleve : eleve;
implementation




Eric.Brasseur@village.uunet.be                                                       96
I.E.P.S.C.F. Marche en Famenne                       Langage orienté gestion ( partie 1)


{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
  assignfile(fnom,'nom.dat');
  {$i-}
  reset(fnom);
  {$i+}
  if ioresult <> 0 then
     begin
       rewrite(fnom);
       closefile(fnom);
       reset(fnom);
     end;
  assignfile(feleve,'eleve.dat');
  {$i-}
  reset(feleve);
  {$i+}
  if ioresult <> 0 then
     begin
       rewrite(feleve);
       closefile(feleve);
       reset(feleve);
     end;
  assignfile(fprenom,'prenom.dat');
  {$i-}
  reset(fprenom);
  {$i+}
  if ioresult <> 0 then
     begin
       rewrite(fprenom);
       closefile(fprenom);
       reset(fprenom);
     end;
  assignfile(fadresse,'adresse.dat');
  {$i-}
  reset(fadresse);
  {$i+}
  if ioresult <> 0 then
     begin
       rewrite(fadresse);
       closefile(fadresse);
       reset(fadresse);
     end;                                       Création et ouverture de mes fichiers
  assignfile(fcp,'cp.dat');
  {$i-}
  reset(fcp);
  {$i+}
  if ioresult <> 0 then
     begin
       rewrite(fcp);
       closefile(fcp);
       reset(fcp);
     end;
  assignfile(flocalite,'localite.dat');
  {$i-}
  reset(flocalite);
  {$i+}
  if ioresult <> 0 then
     begin



Eric.Brasseur@village.uunet.be                                                             97
I.E.P.S.C.F. Marche en Famenne                                               Langage orienté gestion ( partie 1)


      rewrite(flocalite);
      closefile(flocalite);
      reset(flocalite);
    end;
end;

procedure TForm1.bquantiteClick(Sender: TObject);
begin
 try
  nbfiches := strtoint(inputbox('','Nombre de fiches : ','0'));                      Combien de records ?
 except
  on E: Econverterror do showmessage('Du numérique S.V.P.');
 end;
end;

procedure TForm1.BnomClick(Sender: TObject);
var
  i : integer;
begin
  for i := 0 to 99 do
    begin
       unnom.nom := inputbox('Saisie des noms ', 'Nom n° ' + inttostr(i+1) + ' : ','');
       seek(fnom,i);
      write(fnom,unnom);
    end;
end;

procedure TForm1.BprenomClick(Sender: TObject);
var
  i : integer;
begin
  for i := 0 to 99 do
    begin
       unprenom.prenom := inputbox('Saisie des prénoms ', 'Prénom n° ' + inttostr(i+1) + ' : ','');
       seek(fprenom,i);
      write(fprenom,unprenom);
    end;
end;

procedure TForm1.BadresseClick(Sender: TObject);
var
  i : integer;
begin
  for i := 0 to 99 do
    begin
       unadresse.adresse := inputbox('Saisie des adresses ', 'adresse n° ' + inttostr(i+1) + ' : ','');
       seek(fadresse,i);
      write(fadresse,unadresse);
    end;
end;


procedure TForm1.BlocaliteClick(Sender: TObject);
var
 i : integer;
begin
 for i := 0 to 99 do
   begin
      unlocalite.localite := inputbox('Saisie des localites ', 'localite n° ' + inttostr(i+1) + ' : ','');
      seek(flocalite,i);



Eric.Brasseur@village.uunet.be                                                                                     98
I.E.P.S.C.F. Marche en Famenne                                              Langage orienté gestion ( partie 1)


     write(flocalite,unlocalite);
  end;
end;

procedure TForm1.BcpClick(Sender: TObject);
var
  i : integer;
begin
  for i := 0 to 99 do
    begin
       uncp.cp := inputbox('Saisie des cps ', 'cp n° ' + inttostr(i+1) + ' : ','');
       seek(fcp,i);
      write(fcp,uncp);
    end;
end;

procedure TForm1.BcreationClick(Sender: TObject);
var
 i : integer;
begin
 ok.text := '';
 randomize;
 for i := 0 to nbfiches - 1 do
   begin
     seek(fnom, random(99));
     read(fnom, unnom);
     seek(fprenom, random(99));
     read(fprenom, unprenom);
     seek(fadresse, random(99));                                         Génération du fichier élève
     read(fadresse, unadresse);
     seek(fcp, random(99));
     read(fcp, uncp);
     seek(flocalite, random(99));
     read(flocalite, unlocalite);
     seek(feleve,i);
     uneleve.nom := unnom.nom;
     uneleve.prenom := unprenom.prenom;
     uneleve.adresse := unadresse.adresse;
     uneleve.cp := uncp.cp;
     uneleve.localite := unlocalite.localite;
     write(feleve,uneleve);
   end;
 ok.text := 'Terminé';
end;

end.




Eric.Brasseur@village.uunet.be                                                                                    99
I.E.P.S.C.F. Marche en Famenne                                                                            Langage orienté gestion ( partie 1)


1. INTRODUCTION. ............................................................................................................... 1
  1.2. Considérations générales. ............................................................................................................................ 1
  1.2. Remarques particulières concernant DELPHI. ............................................................................................ 1
2. NOTIONS DE BASE. .......................................................................................................... 2
  2.1. Types de variables. ...................................................................................................................................... 2
  2.2. La syntaxe. .................................................................................................................................................. 3
  2.3. L'environnement de travail de DELPHI. ..................................................................................................... 4
3. LES PREMIERS PAS EN PROGRAMMATION. ........................................................... 13
  3.1.   Les opérateurs arithmétiques. .................................................................................................................... 13
  3.2.   Les conversions de type de variables. ....................................................................................................... 14
  3.3.   Les branchements conditionnels ( ou les instructions de test ). ................................................................. 18
  3.4.   La structure de choix multiples. ............................................................................................................... 22
  3.5.   Les structures répétitives. .......................................................................................................................... 24
  3.6.   La manipulation des tableaux. ................................................................................................................... 28
4. QUELQUES COMPOSANTS DE DELPHI. .................................................................... 32
  4.1.   Les groupbox et les radiobutton. ............................................................................................................... 32
  4.2.   Les cases à cocher. .................................................................................................................................... 33
  4.3.   Les ComboBox ( Boîtes à options). .......................................................................................................... 33
  4.4.   Les boîtes à listes ( listbox ). ..................................................................................................................... 36
5. LES PROCEDURES ET LES FONCTIONS. .................................................................. 37
  5.1.   Avantages et inconvénients de la programmation procédurale. ............................................................... 37
  5.2.   Les sous-programmes en langage Pascal. ................................................................................................. 37
  5.3.   Le passage des paramètres à une procédure ou fonction. .......................................................................... 44
  5.4.   La récursivité. ............................................................................................................................................ 47
6. LES FICHIERS. ................................................................................................................ 52
  6.1.   Déclaration. ............................................................................................................................................... 52
  6.2.   Ouverture et fermeture du fichier. ............................................................................................................. 53
  6.3.   Lecture et écriture dans un fichier. ............................................................................................................ 53
  6.4.   Exemple : le fichier client ( version 1 ). .................................................................................................... 54
  6.5.   Positionnement et affichage d'un record sélectionné. ................................................................................ 57
  6.6.   Modification d'un record Ŕ Suppression d'un record Ŕ Travail multi-fichiers. .......................................... 63
7. LES RECHNIQUES DE TRI, LES FUSIONS, LES TECHNIQUES DE
RECHERCHE. ........................................................................................................................ 78
  7.1. Tri par extraction simple. .......................................................................................................................... 78
  7.2. Tri par permutation simple. ...................................................................................................................... 80
  7.3. Tri par permutation répétée. ...................................................................................................................... 82
  7.4 . Le quicksort. ............................................................................................................................................. 83
  7.5. Le tri à plusieurs critères. .......................................................................................................................... 86




Eric.Brasseur@village.uunet.be                                                                                                                                    100

				
DOCUMENT INFO
Shared By:
Categories:
Tags:
Stats:
views:16
posted:11/26/2011
language:French
pages:100