COURS DE · Web viewC'est à ce niveau que l'on placera toutes les instructions à effectuer afin...

41
COURS

Transcript of COURS DE · Web viewC'est à ce niveau que l'on placera toutes les instructions à effectuer afin...

COURS DE

COURS

©HOFMANS Pierre

Septembre 2011

PARTIE 1 : INTRODUCTION GENERALE1

1.Evolution des langages informatiques1

2.Importance de l'informatisation1

3.Introduction générale aux algorithmes1

PARTIE 2 : LES ALGORITHMES4

1.Introduction4

2.Structure d'un algorithme4

A.Le pseudo-code4

B.L'ordinogramme5

3.Les variables6

A.Utilité6

B.Déclaration et types élémentaires6

C.Différences entre les constantes, les variables et les structures7

D.Les opérateurs8

E.Affectation8

F.Utilisation9

4.Les sous-algorithmes10

A.Introduction10

B.Les échanges d'information10

C.Fonction ou Procédure ?11

D.Déclaration et appel d'une procédure11

E.Déclaration et appel d'une fonction12

F.La portée des variables13

5.Les alternatives13

A.Les alternatives à 2 branches14

B.Les conditions14

C.Les alternatives imbriquées15

D.Les conditions composées16

E.Les alternatives multiples17

6.Les répétitives17

A.Introduction17

B.Les répétitives avec compteur18

C.Les répétitives "Tous les éléments d'une liste"19

D.Les répétitives conditionnelles19

E.Les répétitives imbriquées20

7.Les tableaux20

A.Déclaration d'un tableau21

B.Initialisation d'un tableau22

C.Lecture d'un tableau23

D.Modification d'un tableau23

E.Les tableaux à 2 dimensions24

8.Les chaînes de caractères24

A.Les caractères25

B.Les chaînes de caractères25

9.Les fichiers26

A.Introduction générale26

B.Organisation des fichiers26

C.Les structures27

D.Les types d'accès28

E.Les fichiers séquentiels29

10.Les fichiers indexés et bases de données32

A.Introduction32

B.Notion de liens entre les fichiers33

C.Les fichiers indexés33

D.Les opérations de base34

LES ALGORITHMES

© Pierre Hofmans

13.08.12

Evolution des langages informatiques

Le terme "informatique" vient des mots "information" et "automatique". Il désigne à l'origine l'ensemble des systèmes d'automatisation du traitement de l'information.

Un des premiers langages les plus répandus dans les entreprises, à savoir le COBOL, était (et est encore) tout particulièrement destiné à traiter un grand nombre de données afin de faciliter la gestion de l'entreprise au niveau administratif essentiellement (comptabilité, factures, etc.).

Les modes de communication s'étant fortement développés ces dernières années (internet, iPad, etc.), les entreprises ont souhaité faire évoluer leurs systèmes informatiques pour tirer profit de ces nouveautés. De nouveaux langages et pratiques ont alors été conçus afin de répondre à ces besoins (programmation orientée objets, Java, JavaScript, etc.).

Importance de l'informatisation

L'informatisation d'une entreprise (ou même d'un simple département) est un moment très important dans la vie d'une société. En effet, lorsque le travail est fait correctement, il se déroule en plusieurs étapes dont :

-La phase, peut-être la plus importante, consistant notamment à analyser les besoins et souhaits. Cette étape est, en effet, cruciale car c'est elle qui va permettre de définir clairement les besoins et souhaits informatiques de l'entreprise. Mais elle est également très importante car on profitera de cette période et des questions posées par les analystes pour valider et souvent améliorer les processus administratifs et/ou de production en cours d'examen.

-La phase correspondant au développement des programmes. Cette phase étant elle-même divisée en 2 parties : l'analyse et la programmation. Ici, l'analyse consistera "simplement" à définir les algorithmes qui permettront aux développeurs d'écrire les programmes.

Introduction générale aux algorithmes

Il existe beaucoup de définitions différentes du mot algorithme. Des plus simples aux plus compliquées.

En voici quelques unes :

-Un algorithme est une suite finie et non-ambiguë d’instructions permettant de donner la réponse à un problème.

-C'est un ensemble d'instructions permettant de résoudre un problème.

-C'est l'étude de la résolution de problèmes par la mise en œuvre de suites d'opérations élémentaires selon un processus défini aboutissant à une solution.

Ou, en d'autres mots, un algorithme est une suite précise d'instructions ordonnées qui permettent d'accomplir une tâche spécifique.

On en rencontre dans notre vie de tous les jours sous diverses formes depuis des siècles (ex.: recette de cuisine, utilisation d'un appareil, notice de montage, plan pour la construction d'une habitation, etc.)

En informatique, les algorithmes sont écrits par les analystes-programmeurs lors de la seconde phase de l'informatisation. Ces algorithmes décriront avec précision le traitement que les programmeurs devront effectuer dans leurs programmes.

Mais, s'ils sont écrits avec tant de précision, à quoi servent-ils ? Pourquoi ne pas directement écrire les programmes ? Et bien, pour plusieurs raisons :

-La première étant le fait qu'à cette étape de l'informatisation, on souhaite être indépendant des particularités techniques de tel ou tel autre langage informatique.

-La seconde étant, qu'à ce stade, on n'a pas encore une idée assez claire des différentes étapes à programmer. Le "langage" utilisé dans les algorithmes étant nettement plus compréhensible par le commun des mortels que le langage technique de l'ordinateur, il lui sera préféré.

-De plus, en suivant le principe de base de la programmation qui dit que Tout problème compliqué peut être décomposé en plusieurs problèmes plus simples, ayant chacun une solution simple, cette méthodologie (à savoir analyse détaillée, puis programmation) permet à plusieurs développeurs de travailler en équipe, tout en assurant une meilleure qualité des programmes.

Nous verrons dans ce cours qu'il existe plusieurs langages de description d'algorithme (LDA) dont le pseudo-code, les ordinogrammes, les arbres programmatiques, etc. Comme vous pourrez le constater, ils sont tous facilement compréhensibles par toute personne ayant un minimum de logique.

Attention, avant de passer à l'étude proprement dite des algorithmes, n'oublions jamais ces quelques principes de base :

-Ce qui se conçoit bien, s'énonce clairement.En d'autres mots, il faut travailler de manière structurée et organisée afin d'éviter les développements "spaghettis" (où l'on ne voit ni le début, ni la fin).

-Toujours écrire un algorithme (ainsi qu'un programme) en pensant que vous ou quelqu'un d'autre devra le mettre au point, mais aussi le modifier un jour.Il faut donc qu'il soit écrit proprement, soit lisible, contienne des commentaires, respecte les standards de programmation de l'entreprise, etc.

-Un ordinateur ne réfléchit pas et obéit au doigt et à l'œil sans se préoccuper de savoir si ce que l'on lui demande est correct. C'est donc aux développeurs d'y veiller et de prévoir tous les cas.

S'il est vrai qu'avoir un esprit logique facilite la rédaction des algorithmes, il n'est pas indispensable. L'expérience acquise permet de pallier un éventuel manque. Il faut avant tout être méthodique et rigoureux.

Au début de votre "carrière", il faudra, à chaque fois que vous aurez écrit une série d’instructions, vérifier votre code en vous mettant systématiquement à la place de la machine qui va les exécuter. Pour cela, il vous suffira de parcourir les instructions les unes après les autres et écrire sur une feuille les résultats obtenus. Et si ceux-ci ne correspondent pas à ceux souhaités, chercher où se trouve l'erreur, la corriger et recommencer le contrôle. Petit à petit, à force de pratique, vous verrez vos progrès !

13.08.12Page 34

1. Introduction

Les ordinateurs sont capables de comprendre 4 types d'instructions :

-L'affectation des variables

-Les commandes de lecture/écriture (clavier, fichier, écran, etc.)

-Les tests

-Les boucles

Un algorithme en informatique est toujours une combinaison de ces 4 types d'instructions. Il peut y en avoir quelques unes, quelques dizaines ou plusieurs milliers.

Structure d'un algorithme

Avant d'étudier les différentes instructions composant un algorithme, il est intéressant d'en voir la structure générale, et ce même si cela risque d'être un peu obscur pour l'instant. Dans la suite du cours, nous reviendrons sur chaque partie de l'algorithme afin de l'examiner plus en détail.

Le pseudo-code

Comme vous pouvez le constater sur le schéma précédent, un algorithme est composé de plusieurs parties :

-L'en-tête qui reprend le nom de l'algorithme ainsi qu'un commentaire décrivant brièvement le rôle du programme.

-La partie suivante concerne la déclaration des variables en général. Celles-ci sont en fait classifiées en 3 catégories : les constantes, les variables et les structures.

-La troisième partie est dédiée aux fonctions et procédures. Celles-ci sont en fait des sortes de sous-programmes que l'on appelle pour exécuter une tâche bien précise. Ces "sous-programmes" permettent de soulager la partie principale du traitement en évitant, par exemple, de devoir y écrire un traitement que l'on souhaite exécuter à plusieurs reprises à des moments différents.

-Et, enfin, la dernière partie qui est aussi la plus importante : le corps de l'algorithme. C'est à ce niveau que l'on placera toutes les instructions à effectuer afin de permettre au programme qui sera écrit à partir de ce pseudo-code de remplir son rôle.

L'ordinogramme

Si le pseudo-code est une des méthodes les plus utilisées par les informaticiens pour représenter un algorithme, l'ordinogramme est souvent préféré par les débutants grâce à sa représentation graphique. S'il est effectivement plus visuel et donc plus vite compréhensible, il ne convient toutefois pas aux longs traitements.

Les variables

1. Utilité

Lorsque l'on programme, on doit souvent demander à l'ordinateur de retenir certaines informations pendant le traitement. Ces informations, ou données, sont de différents types : nombres, caractères, dates, etc.

Ces informations seront stockées par l'ordinateur dans des zones de sa mémoire que l'on peut comparer à des tiroirs d'une armoire. On devra simplement placer une étiquette sur chaque tiroir utilisé afin de pouvoir retrouver l'information souhaitée. On pourra alors par la suite facilement relire cette information, mais aussi la modifier, voire la supprimer.

En informatique, un tiroir est appelé une variable et l'étiquette, son nom.

Déclaration et types élémentaires

Dans la plupart des langages, chaque variable possède un type et doit être déclarée.

La déclaration sert à :

-Dédicacer une place mémoire de l'ordinateur qui sera exclusivement réservée à cette variable.

-Donner un nom à la variable. Celui-ci permet d'identifier la variable sans équivoque.

-Indiquer le type de la variable (cf. ci-après)

-Fixer la portée de la variable. La variable sera-t-elle globale ou locale ? En d'autres mots, existera-t-elle et pourra-t-on l'utiliser partout dans le programme ou son existence sera-t-elle restreinte à une partie du programme (ex.: une fonction, une boucle, etc.).

Le type d'une variable indique le type d'information que celle-ci pourra contenir :

-Le type entier indique que la variable ne pourra contenir que des nombres entiers (ex.: 124, 0, -253, 123456789).

-Le type réel indique que la variable pourra contenir tous les nombres (ex.: 124.12, 0, -253.523, 12345).

-Le type char indique que la variable ne pourra contenir qu'un seul caractère (ex.: 'a', 'R', '1').Rem.: Dans certaines commandes, il faudra délimiter le caractère en question.       Pour cela, on utilisera les apostrophes.

-Le type chaîne (ou string) indique que la variable pourra contenir une suite de caractères (ex.: "abc", "Bruxelles", "123").Rem.: Dans certaines commandes, il faudra délimiter la chaîne en question.       Pour cela, on utilisera les guillemets.

-Le type booléen indique que la variable ne pourra contenir que deux valeurs : soit vrai (ou true), soit faux (ou false).

-Le type tableau (que nous étudierons plus tard).

Exemple :

Voici un exemple de déclaration de plusieurs variables. Notez bien que la syntaxe utilisée ici n'est pas respectée par tous les analystes. En effet, il n'y a pas de règles rigoureuses et certains informaticiens écriront donc les mêmes instructions légèrement différemment (ex.: Mettre le type de variable à la gauche des noms, mot Programme au lieu de Algorithme au début du code, etc.). L'important dans un pseudo-code est de bien transmettre l'information aux développeurs.

programme exemple1;

varnombre1, nombre2 : entier;

nomEleve1, nomEleve2 : string;

Remarquez que généralement les mots-clés sont écrits en minuscules et soulignés.

Différences entre les constantes, les variables et les structures

Dans le schéma "Structure générale d'un algorithme - pseudo-code", nous pouvons voir qu'il y a 3 sous-groupes au niveau des déclarations des données : les constantes, les variables et les structures. Quelles sont les différences entre ces données ?

Les constantes sont des zones ayant les mêmes caractéristiques que les variables à l'exception du fait que les constantes reçoivent une valeur lors de leur déclaration et que celle-ci ne peut plus être modifiée par la suite dans le programme (D'où le nom de constante).

Les structures, quant à elles, permettent de rassembler plusieurs variables ou constantes sous un même identificateur. Dans certains cas, on parlera aussi d'entités ou d'objets.

programme exemple2;

constMAX : entier ← 100;

TX_TVA1 : réel ← 6.0;

TX_TVA2 : réel ← 12.0;

TX_TVA3 : réel ← 21.0;

varnombre1, nombre2 : entier;

nomEleve1, nomEleve2 : string;

structrectangle :

coinSupGposX : réel;

coinSupGposY : réel;

coinBasDposX : réel;

coinBasDposY : réel;

fstruct

Remarquez que les noms des constantes sont écrits en majuscules.

On attribue une valeur à une constante lors de sa déclaration au moyen de la flèche ← qui indique que la valeur suivante est sauvée dans la zone mémoire.

Les opérateurs

Les opérateurs diffèrent en fonction du type des variables utilisées dans la commande.

Pour les variables numériques, il y a notamment les opérateurs :

-+ : Pour l'addition

-- : Pour la soustraction

-* : Pour la multiplication

-/ : Pour la division (ex.: 7 / 2 = 3.5)

-DIV : Pour la division entière (ex.: 7 DIV 2 = 3)

-MOD : Pour le reste de la division (ex.: 7 MOD 2 = 1)

-↑ : Pour les puissances

Pour les variables alphanumériques (Char et String), il y a notamment :

-+ : Pour la concaténation

Pour les variables booléennes, il y a notamment :

-ET : Pour le ET (AND en anglais)

-OU : Pour le OU (OR en anglais) (→ l'équivalent du ET/OU français)

-OUX : Pour le OU exclusif (XOR en anglais) (→ l'un ou l'autre, pas les deux)

-NON : Pour le NON (NOT en anglais)

Affectation

Affecter une valeur à une variable consiste à attribuer une nouvelle valeur à cette variable. Cette affectation peut s'effectuer de plusieurs manières.

La première étant celle effectuée lors de la déclaration de la variable et la deuxième celle effectuée au cours du traitement. Pour ces deux méthodes, on utilisera toujours la flèche ← comme opérateur.

La syntaxe sera toujours comparable à ceci : nom_variable ← expression. C'est-à-dire le nom de la variable, suivi de la flèche, suivie de la valeur ou d'une expression générant une valeur correspondant au type de la variable.

Une troisième manière d'affecter une valeur à une variable consiste à y placer la valeur tapée au clavier par l'utilisateur ou lue dans un fichier (dans ce cas, on lira plus souvent un enregistrement dont le contenu sera placé dans une structure plutôt qu'une simple variable). Dans ce cas, on utilisera la syntaxe suivante : lire(clavier, variable) ou lire(fichier, variable).

Notons qu'il existe encore une quatrième méthode qui consiste à affecter une valeur aux variables paramètres des fonctions et procédures. Ces affectations se font lors de l'appel ou du retour comme nous le verrons dans la suite du cours.

varnombre1 : entier ← 6;

nomEleve1 : string ← "Pierre";

nombre1 ← 5 + 12 * 7;

lire(clavier, nombre1);

Utilisation

Les variables étant, bien évidemment, très souvent utilisées dans un programme, il est fort difficile de décrire en quelques mots la totalité des différentes utilisations et donc syntaxes existantes. Retenons toutefois pour le moment celles reprises brièvement dans ce chapitre.

La première utilisation d'une variable est son usage dans les commandes d'affectation. Une variable peut se trouver soit à la gauche de la flèche d'affectation, soit à la droite.

Lorsqu'elle se trouve à gauche, cela signifie que le contenu de la variable va être modifié car elle va recevoir le résultat de l'expression se trouvant à la droite de la flèche.

Lorsque la variable se trouve à la droite de la flèche, cela signifie qu'elle ne sera pas modifiée. L'instruction va simplement utiliser son contenu pour calculer le résultat de l'expression.

La deuxième utilisation d'une variable est effectuée lors de la lecture de sa valeur au clavier ou dans un fichier grâce aux commandes lire(clavier, variable) et lire(fichier, variable).

La troisième utilisation d'une variable se rapproche de la deuxième. Elle consiste non pas à lire le nouveau contenu de la variable, mais à afficher à l'écran sa valeur. Cette opération se fait au moyen de la commande écrire(écran, variable).

Notons que cette commande peut également être utilisée pour afficher une valeur sans passer par une variable. Il suffit pour cela de remplacer dans la commande la variable par la valeur. Attention, dans le cas d'une valeur alphanumérique, il faut la mettre entre "" (ou '' pour un caractère) afin que le langage puisse faire la différence entre un nom de variable et un simple texte.

Il existe encore bien d'autres utilisations d'une variable, mais celles-ci étant liées à certaines commandes, elles seront étudiées au fur et à mesure du cours.

Exemple :

Voici un exemple de pseudo-code d'un programme affichant la somme de 2 nombres demandés au clavier.

programme addition;

varnombre1, nombre2, total : réel;

début

lire(clavier, nombre1);

lire(clavier, nombre2);

total ← nombre1 + nombre2;

écrire(écran, total);

fin

Exercice :

Faire l'exercice Cl.

Les sous-algorithmes

1. Introduction

Lorsque l'on écrit un algorithme relativement important, on se rend rapidement compte que l'on effectue à divers endroits les mêmes traitements (ou traitements très similaires). Cela peut aller de la simple vérification d'une valeur encodée (ex.: saisie d'un nombre) à un code nettement plus élaboré (ex.: mise en page avant impression, calculs très compliqués, etc.).

Un programmeur débutant se contentera de répéter plusieurs fois les mêmes commandes aux différents endroits de l'algorithme. Ce n'est bien évidemment pas une bonne manière de procéder. Ce code sera inutilement allongé, sa lisibilité diminuée et le risque d'erreur augmenté. De plus, cela entraînera des problèmes considérables de maintenance car en cas de modification du code, il va falloir traquer toutes les apparitions plus ou moins identiques de ce code pour faire convenablement la modification ! Avec le risque d'en oublier certaines...

C'est afin de limiter tous ces problèmes que les sous-algorithmes ont été créés. Un sous-algorithme est un groupe d'instructions qui ne sera exécuté que lorsque l'algorithme principal en a besoin. Celui-ci pourra l'exécuter autant de fois que nécessaire.

Les avantages des sous-algorithmes sont :

-Ils permettent de n'écrire qu'une seule fois des parties d'algorithmes nécessaires à plusieurs reprises.

-Ils permettent de découper un problème important en plusieurs sous-problèmes plus simples et donc simplifient la conception de l'algorithme.

-Ils augmentent la lisibilité de l'algorithme.

Les échanges d'information

Lorsque l'on écrit un sous-algorithme, il est très important de définir avec précision les informations qui devront être transmises entre le module appelant et le module appelé.

Il existe 3 modes de transfert :

-L'information entrante (IN) : Le module appelant transmet au module appelé une information nécessaire à son exécution (ex.: Un libellé ou code si le sous-module affiche les messages d'erreur à l'écran).

-L'information résultat (OUT) : A la fin de son exécution, le sous-module transmet au programme appelant une information calculée en son sein (ex.: La moyenne d'une série de nombres).

-L'information à modifier (IN/OUT) : Une information utile est transmise au sous-module, celui-ci la traite et la retransmet modifiée au module appelant (ex.: Un tableau contenant une liste de noms à trier).

Notons que les données ainsi transmises sont généralement appelées arguments ou paramètres.

Parallèlement à ces modes de transfert, on parle également de passage des données par valeur ou par adresse.

Le passage par valeur signifie que le module appelant envoie la donnée dans le sens IN (input ou entrée). Le sous-module pourra donc accéder à cette information et la traiter, mais quel que soit le traitement apporté à ce paramètre, la donnée correspondante du programme appelant ne sera pas affectée.

Le passage par adresse signifie que le module appelant n'envoie pas une valeur au sous-module, mais envoie directement l'adresse (ou le pointeur) de la zone mémoire contenant l'information à traiter. Dans ce cas, toute modification effectuée sur cette variable dans le sous-module affectera directement la zone correspondante du module principal puisqu'il s'agit de la même zone mémoire !

Fonction ou Procédure ?

Dans plusieurs langages informatiques, il existe deux grands types de sous-programmes : les procédures et les fonctions.

Une procédure est, tout comme une fonction, une suite d'instructions dédicacées à un traitement bien spécifique et séparée du corps du programme principal.

Une procédure et une fonction se différencient l'une de l'autre par leur appel et les modes de transfert des informations transmises entre le module appelant et le sous-module.

L'appel d'une procédure constitue toujours lui-même une instruction dans le module appelant, alors que celui de la fonction fait partie d'une expression (cf. suite du cours).

Une fonction, dans les langages possédant les deux types de sous-programmes, renvoie toujours une et une seule valeur au programme appelant, alors que les procédures peuvent en renvoyer 0, 1 ou plusieurs (cf. suite du cours). De plus, les paramètres de ces mêmes fonctions sont toujours du type IN.

Déclaration et appel d'une procédure

Une procédure est toujours composée de plusieurs éléments :

1)Le mot proc ou procedure

2)Le nom de la procédure

3)Entre parenthèses, les éventuels paramètres séparés par des virgules. Attention, les parenthèses doivent être présentes même s'il n'y a aucun paramètre.Attention, dans un algorithme, on doit indiquer pour chaque paramètre :- Son nom- Son mode de transfert (IN, OUT, IN/OUT)- Son type (entier, réel, string, etc.)

4)La définition des variables locales (spécifiques à la procédure)

5)Le mot debut-proc pour indiquer le début des instructions de la procédure

6)Les instructions de la procédure

7)Le mot fin-proc ou fin-procedure

L'appel d'une procédure est très simple, il suffit de taper son nom suivi des parenthèses. Entre parenthèses, on tapera la valeur des paramètres éventuels.

Exemple :

Créons un module principal qui appelle une procédure qui calcule la TVA sur le prix reçu en paramètre et qui renvoie au module appelant le montant de la TVA et le prix TVAC. Le module principal affiche ensuite le prix avec TVA à l'écran.

programme trtPrix;

varprxHTVA, mnTVA, prxTVAC : réel;

proc calculeTVA (IN prixHTVA : réel,

OUT mntTVA : réel,

OUT prixTVAC : réel)

debut-proc

mntTVA ← prixHTVA * 21 / 100;

prixTVAC ← prixHTVA + mntTVA;

fin-proc

début

lire(clavier, prxHTVA);

calculeTVA(prxHTVA, mnTVA, prxTVAC);

écrire(écran, prxTVAC);

fin

Déclaration et appel d'une fonction

Une fonction est toujours composée de plusieurs éléments :

1)Le mot fonc ou fonction

2)Le nom de la fonction

3)Entre parenthèses, les éventuels paramètres séparés par des virgules. Attention, les parenthèses doivent être présentes même s'il n'y a aucun paramètre.Attention, dans un algorithme, on doit indiquer pour chaque paramètre :- Son nom- Son type (entier, réel, string, etc.)

4)Le type (entier, réel, string, etc.) du résultat de la fonction

5)La définition des variables locales (spécifiques à la fonction)

6)Le mot debut-fonc pour indiquer le début des instructions de la fonction

7)Les instructions de la fonction

8)Au moins une instruction de retour au module appelant et de renvoi du résultat de la fonction

9)Le mot fin-fonc ou fin-fonction

L'appel d'une fonction est très simple, il suffit de taper, dans une expression, son nom suivi des parenthèses. Entre parenthèses, on tapera la valeur des paramètres éventuels.

Exemple :

Créons un module principal qui appelle une fonction qui calcule la TVA sur le prix reçu en paramètre et qui renvoie au module appelant le montant de la TVA. Le module principal affiche ensuite le prix avec TVA à l'écran.

programme trtPrix;

varprxHTVA : réel;

fonc calculeTVA (prixHTVA : réel) : réel

varmntTVA : réel;

debut-fonc

mntTVA ← prixHTVA * 21 / 100;

retour mntTVA;

fin-fonc

début

lire(clavier, prxHTVA);

écrire(écran, prxHTVA + calculeTVA(prxHTVA));

fin

Notons encore que lorsqu'une fonction retourne une valeur, son exécution se termine directement. Dans certains cas, cette fonctionnalité sera fort utile lorsque l'on voudra par exemple arrêter l'exécution d'une fonction car certains paramètres sont incorrects, etc. Il suffira alors de taper l'instruction retour;

La portée des variables

Outre leur type, les variables sont également caractérisées par leur portée qui peut être locale ou globale.

Les variables telles que les paramètres et les variables définies au sein d'un sous-module sont dites locales car on ne peut les utiliser que dans celui-ci. Dès que l'on quitte le sous-module, ces valeurs sont perdues définitivement.

Il est possible de définir des variables, dites globales, qui sont accessibles à partir de n'importe quel endroit de l'algorithme. Pour ce faire, on les déclare au début de l'algorithme en dehors de tout sous-module.

Bien que l'utilisation de variables globales soit souvent appréciée par les programmeurs débutants, il est toutefois conseillé d'utiliser les variables locales dès que c'est possible.

Exercice :

Faire l'exercice C2.

Les alternatives

Ce chapitre est dédicacé à l'apprentissage de tout ce qui concerne les outils de test. Ceux-ci sont fort utiles en programmation. Ils permettent de vérifier la validité des valeurs encodées par un utilisateur, de sélectionner le traitement à effectuer en fonction de certaines valeurs, etc.

Une alternative est une instruction qui permet de choisir la partie de code à exécuter en fonction de certaines conditions. Ces dernières sont généralement liées aux valeurs d’une ou plusieurs variables.

1. Les alternatives à 2 branches

Pseudo-code

Ordinogramme

sicondition

alors

instructions Action1;

sinon

instructions Action2;

fin-si

Les groupes d'instructions Action1 et Action2 sont appelés les branches de l'alternative.

Dans une alternative de ce type, la première partie si condition est obligatoire, ainsi que la première branche. La seconde branche est, par contre, facultative.

La partie si condition reprend le test à faire par l'ordinateur au moment où il arrive à ce niveau de l'algorithme.

Si le résultat de l'évaluation de cette condition est vrai (ou true), le système effectuera les instructions de la première branche indiquée par le mot alors.

Si le résultat de l'évaluation de cette condition est faux (ou false), le système effectuera les instructions de la seconde branche indiquée par le mot sinon si elle est présente... Dans le cas contraire, le système n'effectuera aucune instruction particulière.

Quel que soit le résultat du test, l'algorithme se poursuivra par la première instruction située après le fin-si dès que la dernière commande de la branche aura été exécutée.

Notons encore que la partie condition peut être remplacée par une simple variable booléenne.

Les conditions

Lorsqu'une condition n'est pas remplacée par une simple variable booléenne, elle correspond toujours à une comparaison entre deux valeurs. Sa structure est donc toujours semblable à :

valeur1 opérateur de comparaison valeur2

Chaque valeur pouvant être une variable ou une simple valeur (un nombre, du texte, etc.).

Les opérateurs de comparaison sont les signes =, <, <=, >, >= et ≠.

Nous pourrons donc avoir les 6 cas suivants :

a = bSi les valeurs a et b sont égales, le résultat sera true ; dans le cas contraire, il sera false.

a ≠ bSi les valeurs a et b sont différentes, le résultat sera true ; dans le cas contraire, il sera false.

a < bSi a est plus petit que b, le résultat sera true ; dans le cas contraire, il sera false.

a > bSi a est plus grand que b, le résultat sera true ; dans le cas contraire, il sera false.

a <= bSi a est plus petit ou égal à b, le résultat sera true ; dans le cas contraire, il sera false.

a >= bSi a est plus grand ou égal à b, le résultat sera true ; dans le cas contraire, il sera false.

Les alternatives imbriquées

Il arrive, bien évidemment, que les tests ne soient pas toujours aussi simples. Il faudra parfois imbriquer plusieurs tests les uns dans les autres pour arriver à la solution.

Prenons un exemple pour éclaircir tout cela. Supposons que nous devions développer un petit algorithme qui indique si un élève a réussi ou raté son année scolaire. Au premier abord, cela paraît simple à faire :

sirésultat >= 50alors écrire(écran, "réussi");sinon écrire(écran, "raté");fin-si

Mais, il y a un problème. L'école veut qualifier la réussite des élèves. En fait, elle veut que :- Tous les élèves ayant au moins 70% aient la mention "distinction"- Les élèves ayant entre 50% inclus et 70% exclu aient la mention "réussi"- Les élèves ayant moins de 50% aient la mention "raté"

Pseudo-code

Ordinogramme

sirésultat >= 70alors écrire(écran,"distinction");sinon

sirésultat >= 50alors écrire(écran,"réussi");sinon écrire(écran,"raté");fin-si

fin-si

Cette demande ne peut être réalisée au moyen d'une simple alternative à deux branches. En effet, trois situations différentes (et donc trois actions) sont présentes ici.

Dans ce cas, nous avons opté pour la solution des alternatives imbriquées. L'algorithme évalue d'abord le premier test. S'il est positif (true), il exécutera les actions se trouvant dans la branche alors correspondante et poursuivra par les instructions qui suivent l'alternative. Si l'évaluation est négative, il exécutera les instructions de la section sinon correspondante. Celle-ci étant une simple alternative à deux branches, l'algorithme la traitera comme nous l'avons étudié précédemment.

Les conditions composées

Il est parfois nécessaire d'écrire des tests plus complexes qui combinent plusieurs conditions. Dans ce cas, on utilisera également les opérateurs logiques :

ET (AND)Lorsque l'on groupe deux conditions avec cet opérateur, il faut que les deux conditions soient à true pour que le résultat final le soit aussi ; dans tous les autres cas, le résultat final sera false.

OU (OR)Lorsque l'on groupe deux conditions avec cet opérateur, il suffit qu'au moins une des deux conditions soit à true pour que le résultat final le soit aussi. Le résultat final sera false uniquement si les deux conditions le sont aussi.

OUX (XOR)Lorsque l'on groupe deux conditions avec cet opérateur, il faut qu'une et une seule condition soit à true pour que le résultat final le soit aussi. C'est un peu l'équivalent du soit français.

NON (NOT)Est l'opérateur de la négation. En fait, il inverse le résultat d'un test. True devient false, et inversement. Il s'écrit devant la condition.

On peut bien évidemment faire des tests complexes combinant plus de deux conditions. Dans ce cas, il est vivement conseillé d'utiliser les parenthèses pour indiquer dans quel ordre les conditions doivent être vérifiées. Dans le cas contraire, les ET sont prioritaires aux OU.

Attention, lorsque l'on écrit une condition de ce type, il ne faut jamais oublier de se mettre à la place de l'ordinateur et pas à celle de l'utilisateur. En effet, nous ne parlons pas toujours de la même manière. Supposons par exemple que l'on souhaite afficher le nom de tous les habitants de Jette et de Laeken. Comme vous pouvez le constater, un être humain dit généralement qu'il veut les habitants de Jette ET de Laeken. Alors que l'ordinateur devra faire le test si ville = "Jette" OU ville = "Laeken" ! En effet, si l'algorithme contenait un ET, l'ordinateur n'aurait affiché aucun nom car le ET signifie que la ville doit être à la fois égale à Jette et à Laeken... Ce qui est impossible !

Pour écrire correctement un test, il suffit de se mettre à la place d'un ordinateur et se rendre compte qu'il n'a pas la même vue qu'un être humain. Les hommes ont une vue d'ensemble : "On veut tous les habitants de ..." ; les ordinateurs, quant à eux, traitent une donnée (ici, un habitant) à la fois : "Cet habitant habite-t-il à Jette OU à Laeken ?". Si on adopte bien cette vision des choses, nos tests seront bien meilleurs ! Après tout, l'ordinateur est bête, c'est à nous à lui expliquer ce qu'il doit faire ... dans son langage !

Les alternatives multiples

Dans certains cas, il arrive qu'une variable puisse prendre une série de valeurs différentes et que pour chaque valeur un traitement différent doive être effectué. C'est le cas typique des choix multiples.

Dans un algorithme, il est bien évidemment possible d'utiliser les alternatives imbriquées pour traiter ce cas ; mais ce n'est pas une solution très pratique. Dans les cas semblables, il est préférable d'utiliser l'alternative multiple.

Pseudo-code

Ordinogramme

selon que variable

Valeur1 : instructions Action1;

Valeur2 : instructions Action2;

Valeur3 : instructions Action3;

...

ValeurN : instructions ActionN;

autres : instructions ActionN+1;

fin-selon

Le mot-clé autres indique que les instructions correspondantes seront exécutées pour toutes les valeurs absentes de la liste.

Exercice :

Faire l'exercice C3.

Les répétitives

1. Introduction

Les répétitives (ou boucles, ou itératives) sont des instructions spéciales qui permettent de dire à l'ordinateur qu'il doit exécuter plusieurs fois un certain nombre d'opérations, avec éventuellement quelques variantes (exemples : afficher les nombres de 1 à 100, afficher une table de multiplication, etc.).

Les types de répétitives sont très variables d'un langage à l'autre. Ces types se différencient surtout par la façon dont on spécifie le nombre d'itérations. Une itération correspond à UNE exécution des instructions de la boucle.

Deux formes existent : la première, si le nombre de répétitions est connu avant l'exécution de l'instruction de répétition, la seconde s'il n'est pas connu.

Les répétitives avec compteur

Le modèle général de ce type de boucle correspond à :

Pseudo-code

Ordinogramme

répéter pour varCpteur

allant de valInitiale

à valFinale

par pas de valIncrément

...

instructions;

...

fin-répéter

Les instructions se trouvant dans la boucle sont exécutées pour toutes les valeurs d'un compteur (ici : varCpteur) généralement appelé variable de contrôle.

Avant la première itération de la boucle, ce compteur est initialisé à la valeur valInitiale.

Ensuite, avant chaque itération, la commande vérifie si la condition est respectée (la valeur de la variable de contrôle ne peut dépasser la valeur finale varFinale). Si c'est le cas, les instructions de la boucle sont exécutées et, ensuite, le compteur est incrémenté tel que c'est demandé (on ajoute la valeur valIncrément à la variable de contrôle). La boucle s'arrête dès que la condition n'est plus respectée.

Notons qu'il est possible de mettre une valeur d'incrément négative. Dans ce cas, la valeur initiale devra être plus grande ou égale à la valeur finale.

Attention, on ne peut pas modifier la valeur du compteur de la boucle autrement que par la section de l'instruction dédicacée à cet effet sans risquer de perturber le fonctionnement correct de celle-ci.

Attention, comme pour toutes les boucles, il est impératif d'écrire une condition qui ne sera plus respectée à un certain moment, sans quoi vous aurez une boucle infinie et votre programme ne s'arrêtera jamais.

Exemple :

Affichage de la table de multiplication de 5 au moyen d'une boucle :

répéter pour cpteur allant de 1 à 10 par pas de 1

écrire(écran, cpteur, " * 5 = ", cpteur * 5);

fin-répéter

Les répétitives "Tous les éléments d'une liste"

Ce type de répétitive est une variante de l'itérative précédente.

répéter pour variable appartient à liste

...

instructions;

...

fin-répéter

Dans ce cas, la boucle sera exécutée une fois pour chaque élément de la liste. A chaque itération, la variable prendra la valeur de l'élément suivant.

Les répétitives conditionnelles

Comme nous allons le voir dans ce chapitre, en pseudo-code, il existe 4 grands types de répétitives conditionnelles. Il faut toutefois savoir qu'ils sont rarement présents tous les 4 dans un même langage de programmation.

Les quatre modèles sont différenciés les uns des autres en fonction de deux caractéristiques :

-La condition liée à la boucle est-elle une condition de continuation ou d'arrêt ?

-Le test est-il effectué avant ou après la première itération de la boucle ?

condition

continuation

condition

arrêt

test

d'abord

répéter tant que condition

instructions;

fin-répéter

répéter jusqu'à ce que condition

instructions;

fin-répéter

au moins

1 passage

répéter

instructions;

tant que condition

répéter

instructions;

jusqu'à ce que condition

Exemple :

Affichage d'un menu jusqu'à ce que l'utilisateur tape la lettre Q signifiant qu'il souhaite quitter l'application en cours :

répéter

affichageMenu();

lire(clavier, choix);

selon que choix

'A' : ajoutClient();

'M' : modifClient();

'S' : supprClient();

'Q' : /

autres : écrire(écran, "Choix incorrect");

fin-selon

jusqu'à ce que choix = 'Q'

Les répétitives imbriquées

Les instructions placées au sein d'une boucle peuvent être de tout type et, donc, également une autre répétitive. Lorsqu'une itérative est placée au sein d'une autre, on parlera de boucles imbriquées.

Exemple :

Affichage des 10 tables de multiplication :

répéter pour cpteurA allant de 1 à 10 par pas de 1

répéter pour cpteurB allant de 1 à 10 par pas de 1

écrire(écran, cpteurA, " * ", cpteurB, " = ", cpteurA * cpteurB);

fin-répéter

fin-répéter

Exercice :

Faire l'exercice C4.

Les tableaux

Comme vous avez sûrement déjà pu vous en rendre compte, les programmes sont souvent utilisés pour traiter un grand nombre d'informations. Celles-ci sont stockées dans des variables de différents types.

Imaginons à présent que vous souhaitiez faciliter la vie d'un pauvre enseignant qui doit fournir une série de statistiques liées aux résultats obtenus par ses élèves lors des tests effectués au cours de l'année. Pour calculer ces statistiques, il vous faudra dans un premier temps lui demander d'encoder tous les résultats et ensuite il vous suffira de traiter ces valeurs selon les besoins. Facile me direz-vous ! Oui, facile, mais il y a néanmoins un problème de taille. Comment allez-vous, dans l'état actuel de vos connaissances, sauver et ensuite traiter toutes ces données ? Si la classe est composée de 25 élèves et que le professeur a fait 10 tests sur l'année, il faudra déjà 250 variables pour retenir les points ! Et, en plus, vous ne pourrez même pas utiliser une boucle pour effectuer ces traitements, pourtant répétitifs, car les variables ayant des noms différents les unes des autres, vous ne pourrez pas utiliser les mêmes instructions pour les traiter ! Euh ... Facile, aviez-vous dit ?! Ce genre de problème arrivant très fréquemment, les informaticiens ont développé un nouveau type de variable : les tableaux (ou Array en anglais).

En fait, un tableau n'est pas tout à fait une variable, mais est plutôt un ensemble de variables ayant le même nom mais différenciées les unes des autres par un indice (numérique le plus souvent, mais parfois alphanumérique).

Afin de faciliter l'étude des tableaux, je parlerai ici essentiellement des tableaux ayant des indices numériques.

Les tableaux sont donc, schématiquement, composés de cases (ou cellules) numérotées séquentiellement. Attention, les langages diffèrent quant à cette numérotation. En effet, un grand nombre de langages considèrent que la première cellule a pour référence l'indice 1, alors que pour d'autres langages l'indice sera à 0. Les algorithmes n'étant pas liés à un langage spécifique, nous devrons spécifier l'indice de départ au niveau de l'instruction liée à la déclaration/ création du tableau.

Si la première cellule porte le numéro 0, alors la cellule 2 portera le numéro 1, et ainsi de suite.

Cette façon de les nommer est très intéressante au niveau de la programmation car, grâce à cela, on peut facilement accéder (et donc lire ou modifier) une cellule à partir de son numéro.

Grâce à cela, on va également pouvoir utiliser une boucle indicée pour traiter toutes les variables au lieu de devoir écrire le traitement complet pour chaque variable séparément.

1. Déclaration d'un tableau

La déclaration des tableaux diffère d'un langage informatique à l'autre, mais est néanmoins fort stable dans un pseudo-code.

varnomsEleves : tableau [1..30] de string;

Dans cet exemple :

-nomsEleves correspond au nom du tableau.

-tableau indique que cette variable est un tableau.

-Le chiffre 1 correspond à l'indice du premier élément du tableau.Le nombre 30 correspond à l'indice du dernier élément du tableau.Notons qu'un grand nombre de langages réservent dès le départ la place nécessaire pour retenir tout le tableau en mémoire. Pour ce faire, ils ont besoin de connaître le nombre maximum d'éléments du tableau dès sa déclaration. D'autres langages, par contre, travaillent autrement et sont capables de faire varier la taille du tableau en fonction de son contenu à un instant T.

-string indique que le tableau contiendra des données du type string.Notons qu'un grand nombre de langages imposent le fait que tous les éléments d'un tableau soit du même type. D'autres langages, quant à eux, permettent de mélanger les types (deux cellules pourraient ainsi être de types différents).

Initialisation d'un tableau

L'initialisation d'un tableau consiste à initialiser chacun de ses éléments les uns après les autres.

Pour ce faire, on utilise souvent une boucle semblable à celle-ci :

varnomsEleves : tableau [1..30] de string;

moyenneEleves : tableau [1..30] de réels;

...

répéter pour i allant de 1 à 30 par pas de 1

nomsEleves [i] ← "";

moyenneEleves [i] ← 0;

fin-répéter

Ces instructions permettent d'être certain que le tableau est propre et prêt à être utilisé ; qu'aucune "crasse" pouvant perturber les traitements futurs n'y soit stockée par erreur.

Attention, cet exemple n'est qu'une des méthodes d'initialisation d'un tableau. En effet, à la fin de ce traitement le tableau est vide ; mais certaines initialisations consistent à charger le tableau avec les valeurs initiales telles que les noms des élèves, etc. Dans ce cas, plusieurs cas peuvent se présenter :

-On initialise les éléments les uns après les autres en copiant, dans une boucle, les valeurs venant d'un autre tableau ou d'une base de données.

varnomsEleves : tableau [1..30] de string;

nomsParents : tableau [1..30] de string;

...

répéter pour i allant de 1 à 30 par pas de 1

nomsParents [i] ← nomsEleves [i];

fin-répéter

-On initialise les éléments les uns après les autres en demandant, dans une boucle, les valeurs les unes après les autres à l'utilisateur via une commande du style lire(clavier, nomTableau[i])

varnomsEleves : tableau [1..30] de string;

...

répéter pour i allant de 1 à 30 par pas de 1

écrire(écran, "Encodez l'élève ", i);

lire(clavier, nomsEleves [i]);

fin-répéter

-On initialise les éléments les uns après les autres via une simple commande d'affectation écrite directement dans le programme. Dans ce cas, aucune boucle n'est possible.

varnomsEleves : tableau [1..30] de string;

...

nomsEleves [1] ← "Amarandie";

nomsEleves [2] ← "Bizancia";

nomsEleves [3] ← "Coralinia";

...

Lecture d'un tableau

L'accès à une valeur d'un tableau est relativement simple. Il suffit de taper le nom de la variable liée au tableau, suivi de l'indice correspondant à la valeur souhaitée entre crochets. L'indice peut être un nombre ou une variable numérique.

Pour afficher la totalité d'un tableau, il suffit donc de créer une boucle qui en affiche chaque élément l'un après l'autre.

A ce niveau, il est nécessaire d'introduire la notion de taille du tableau. Si certaines variantes existent au sein des différents langages informatiques, il faut savoir qu'au niveau des algorithmes, un tableau a deux tailles : sa taille maximale et sa taille réelle. La taille maximale est celle définie lors de la déclaration du tableau : le tableau ne pourra pas contenir plus d'éléments que prévu. La taille réelle quant à elle indique le nombre d'éléments actuellement présents dans le tableau (En réalité, cette taille correspond à la position occupée par le dernier élément du tableau). Attention, cette taille doit être gérée par le développeur dans un algorithme. En effet, contrairement à certains langages, cette information n'est pas directement gérée par le système.

Exemple : Afficher le contenu d'un tableau

varnomsEleves : tableau [1..30] de string;

taille : entier;

...

nomsEleves [1] ← "Amarandie";

nomsEleves [2] ← "Bizancia";

nomsEleves [3] ← "Coralinia";

nomsEleves [4] ← "Doriania";

taille ← 4;

...

répéter pour i allant de 1 à taille par pas de 1

écrire(écran, nomsEleves [i]);

fin-répéter

Modification d'un tableau

Pour modifier la valeur d'un élément du tableau, on procède de la même manière que pour une simple variable.

nomsEleves [3] ← "Eléonore";

Pour ajouter une nouvelle valeur à la fin du tableau, on peut procéder de la même façon, mais sans oublier de tester s'il reste de la place dans le tableau et de mettre à jour la variable contenant sa taille réelle :

// Ajout d'un élément à la fin (30 = taille max)

si taille < 30

alorstaille ← taille + 1;

nomsEleves [taille] ← "Floraline";

sinonécrire(écran, "Erreur : tableau plein");

fin-si

Les tableaux à 2 dimensions

Jusqu'à présent, nous n'avons étudié que les tableaux à une dimension (ex.: les noms des élèves d'une classe, une liste de voitures). On peut néanmoins créer des tableaux à plusieurs dimensions. Par exemple, un tableau à 2 dimensions qui reprendrait les points de tous les élèves d'une classe.

Pour déclarer un tableau de ce type, on utilisera la syntaxe suivante :

varptsEleves : tableau [1..30,1..10] d'entiers;

Notons que d'un point de vue algorithmique, tous les éléments d'un tableau doivent être du même type. Donc si l'on veut un tableau reprenant le nom des élèves et leurs points, il faut en fait créer deux tableaux : un pour les noms et un autre pour les points. Il faut néanmoins veiller à ce que les indices correspondent d'un tableau à l'autre (ex.: L'indice du tableau des noms des élèves correspondra au premier indice du tableau des points. Ainsi, on pourra être sûr que les points du 5ème élément du deuxième tableau correspondront à l'élève du 5ème élément du tableau des noms).

Pour accéder à une cellule d'un tableau à deux dimensions, il suffit de spécifier les deux indices :

ptsEleves [3,5] ← 10;

Pour initialiser un tableau de ce type, on procèdera de la manière suivante :

varptsEleves : tableau [1..30,1..10] d'entiers;

...

répéter pour i allant de 1 à 30 par pas de 1

répéter pour j allant de 1 à 10 par pas de 1

ptsEleves [i,j] ← 0;

fin-répéter

fin-répéter

Si on a pu créer un tableau à 2 dimensions, il faut savoir que l'on peut créer des tableaux à plusieurs dimensions en procédant de la même manière. En informatique conceptuelle, il n'y a pas de limite au nombre de dimensions. La seule limite est la représentation humaine (1 dimension → une ligne ou une colonne de cellules ; 2 dimensions → un tableau de cellules ; 3 dimensions → un cube ou un parallélépipède rectangle de cellules ; 4 dimensions → euh...).

Exercice :

Faire l'exercice C5.

Les chaînes de caractères

Après avoir vu les variables et les tableaux et avant d'étudier les fichiers, il est intéressant de revenir quelques instants sur les chaînes de caractères.

1. Les caractères

Les caractères constituent un type de données présent dans la grande majorité des langages. Si de prime abord ce type de données paraît simple (il contient un caractère qui peut être un chiffre, une lettre, etc.), on constatera qu'il peut différer en fonction d'un système (langage, compilateur, etc.) à l'autre et qu'il est donc important d'un peu mieux comprendre son fonctionnement.

Il faut savoir qu'il existe plusieurs ensembles de caractères en informatique : ASCII, EBCDIC, Unicode, etc. Un ensemble de caractères correspond à une liste des caractères autorisés. Celle-ci est triée et codifiée : à chaque caractère correspond un code qui représente sa valeur et sa position dans la liste. Le problème vient du fait que malheureusement ces listes n'ont pas toutes les mêmes possibilités suite à leur système de codification → Certains caractères spéciaux ne sont présents que dans une liste. De plus, elles ne sont pas triées de la même manière : en ASCII, les caractères sont triés suivant l'ordre : chiffres - lettres majuscules - lettres minuscules ; en EBCDIC, l'ordre est : lettres minuscules - lettres majuscules - chiffres.

Lorsque l'on demande de comparer deux caractères, sauf traitement spécial (ex.: Ne pas faire de différence entre une lettre minuscule et la lettre majuscule correspondante), les langages informatiques comparent simplement les codes qui correspondent aux caractères et leurs positions dans la liste codifiée.

1. Les chaînes de caractères

Une chaîne de caractères est une suite ordonnée de 0, 1 ou plusieurs caractères que l'on peut manipuler globalement ou caractère par caractère.

Elle peut être :

-de longueur fixe (ex.: CHAR(10) en SQL)

-de longueur variable avec un maximum (ex.: VARCHAR(30) en SQL)

-de longueur variable sans maximum (ex.: String en JavaScript)

Dans certains langages, une chaîne de caractères est simplement un tableau dont chaque élément correspond à un caractère.

Pour rappel, dans un programme, on rencontre les chaînes sous leurs deux formes principales : les littéraux (= texte entouré de "") et les variables.

Si les langages modernes offrent de nombreuses fonctions liées aux chaînes de caractères, ce n'est pas le cas de tous les langages, ni des instructions disponibles pour les algorithmes généraux.

Les commandes de base disponibles sont :

-La concaténation effectuée via l'opérateur + (ex.: "Bal" + "le" → "Balle")

-Les opérateurs de comparaison =, ≠, <, <=, > et >=Attention, le système tient compte de l'ensemble de caractères actif lors des tests de comparaison.

-La fonction longueur(chaîne) qui renvoie la longueur actuelle du contenu de la chaîne (qui peut différer de la taille maximale de la zone)

-L'accès direct à un caractère précis de la chaîne s'écrit soit maChaine[i] (lorsque l'on considère qu'une chaîne de caractère est l'équivalent d'un tableau de caractères), soit maChaine.charAt(i) lorsque l'on considère la chaîne de caractères comme un type de variable spécifique.Dans les 2 écritures, maChaine sera remplacée par le nom de la variable et i par l'indice représentant la position du caractère dans la chaîne. Attention, comme pour les tableaux, certains systèmes considèrent que la première position est la position 0, d'autres la définissent comme la position 1. A vous d'être clairs et cohérents dans vos algorithmes !

Les fichiers

1. Introduction générale

Jusqu’à présent, les informations utilisées dans les algorithmes sont soit directement écrites par le programmeur, soit encodées par l'utilisateur à chaque exécution. Il est évident que cela ne suffit pas. Il faut qu'un utilisateur puisse introduire ses propres données sans être tributaire du programmeur et ces données doivent pouvoir être conservées d'une exécution à l'autre. C'est pourquoi les fichiers et les bases de données ont été développés.

Dans ce chapitre nous étudierons principalement les fichiers séquentiels ; les bases de données seront décrites dans le chapitre suivant.

1. Organisation des fichiers

Un premier grand critère qui différencie les deux grandes catégories de fichiers est le suivant : le fichier est-il ou non organisé sous forme de lignes successives ? Si oui, cela signifie vraisemblablement que ce fichier contient le même genre d'information à chaque ligne. Ces lignes sont alors appelées des enregistrements.

Prenons pour exemple un fichier contenant l'ensemble des renseignements sur les lecteurs d'une bibliothèque. Pour chaque lecteur, il faudra retenir des informations telles que le nom, le prénom, la date de naissance, etc. Dans ce cas, il peut paraître plus simple de stocker une personne par ligne du fichier (par enregistrement). En d'autres mots, quand on lira une ligne, on sera sûr qu'elle contient les informations concernant une personne, et uniquement cela. Un fichier ainsi codé sous forme d'enregistrements est appelé un fichier texte.

En fait, entre chaque enregistrement, un code (composé des caractères CR et LF) est placé dans le fichier afin de signifier un changement de ligne. Le plus souvent, le langage de programmation, dès lors qu'il s'agit d'un fichier texte, gèrera lui-même la lecture et l'écriture de ce code à chaque fin de ligne. Le programmeur, lui, n'aura qu'à dire au système de lire ou d'écrire une ligne.

Ce type de fichier est couramment utilisé dès lors que l'on doit stocker des informations pouvant être assimilées à une base de données.

Le second type de fichiers, à savoir les fichiers binaires, regroupe les fichiers (ex.: une image, un programme exécutable, etc.) qui ne possèdent pas de structure de lignes (d'enregistrements). Les bytes, quels qu'ils soient, sont écrits séquentiellement. Naturellement, leur structure différente implique un traitement différent par le programmeur.

Il est toutefois toujours possible d'opter pour une structure binaire même dans le cas où le fichier représente une base de données.

Autre différence majeure entre fichiers texte et fichiers binaires : dans un fichier texte, toutes les données sont écrites sous forme de texte. Cela veut dire que les nombres y sont représentés sous forme de suite de caractères. Ces nombres doivent donc être convertis en chaînes lors de l'écriture dans le fichier. Inversement, lors de la lecture du fichier, on devra convertir ces chaînes en nombre si l'on veut pouvoir les utiliser dans des calculs. En revanche, dans les fichiers binaires, les données sont écrites à l'image exacte de leur codage en mémoire RAM, ce qui épargne toutes ces opérations de conversion.

Ceci a comme autre implication qu'un fichier texte est directement lisible, alors qu'un fichier binaire ne l'est pas (sauf bien sûr en écrivant soi-même un programme approprié). Si l'on ouvre un fichier texte via un simple éditeur, on y reconnaîtra toutes les informations (ce sont des caractères stockés comme tels). La même chose avec un fichier binaire n'affichera qu'une suite de caractères incompréhensibles.

1. Les structures

Une structure est un type de donnée composée de plusieurs parties qui sont elles-mêmes des données. Les différentes parties, souvent appelées les "champs", peuvent être de types différents. La structure peut être manipulée comme un tout, et chacun des champs peut être manipulé individuellement.

Si une variable est déclarée relevant d'un type de structure, le nom de la variable désignera l'ensemble de la structure, et une appellation combinant le nom de la variable et le nom du champ (séparés par un point ou le caractère →) désignera un champ individuel.

structstrLivre :

titre : string;

auteurs : string;

nbreEmprunts : entier;

fstruct

var enregLivre : strLivre;

...

lire(fichier, enregLivre);

écrire(écran, enregLivre.titre);

...

Comme vous pouvez le constater dans cet exemple, généralement, quand on lit un fichier, on lit un enregistrement. Ce dernier étant également structuré dans les fichiers de données, on fera en sorte que la variable chargée lors de la lecture du fichier réponde à la même structure afin de pouvoir accéder facilement à chaque champ.

Si nous nous intéressons un peu plus au côté technique, nous apprendrons qu'il y a deux grandes possibilités de structurer les enregistrements : par délimitation et par champs de longueur fixe.

-La délimitation consiste à indiquer la fin d'un champ par un caractère spécial (qui doit bien évidemment être strictement interdit à l'intérieur des champs) qui permet de repérer quand finit un champ et quand commence le suivant.

-Le second procédé consiste à indiquer dès le départ la longueur de chaque champ. Les champs sont sauvés dans le fichier en respectant scrupuleusement ces longueurs. Il n’y a donc pas de caractère de délimitation, mais on sait que les x premiers caractères de chaque ligne stockent le premier champ, les y suivants le deuxième champ, etc.

L’avantage de la délimitation est son faible encombrement en place mémoire ; il n’y a aucun espace perdu, et un fichier texte codé de cette manière occupe le minimum de place possible. Mais elle possède en revanche un inconvénient majeur, qui est la lenteur de la lecture. En effet, chaque fois que l’on récupère une ligne dans le fichier, il faut alors parcourir un par un tous les caractères pour repérer chaque occurrence du caractère de séparation avant de pouvoir découper cette ligne en différents champs.

Le second procédé, à l’inverse, gaspille de la place mémoire puisque le fichier est rempli d'espaces vides à la fin des champs non remplis. Mais d’un autre côté, la récupération des différents champs est très rapide. Lorsqu’on lit une ligne, il suffit de la découper en différentes chaînes de longueur prédéfinie.

A l’époque où la place mémoire coûtait cher, la structure délimitée était souvent privilégiée. Mais depuis bien des années, on opte de plus en plus souvent pour la structure en champs de longueur fixe.

Remarque :

Lorsqu'on choisit de coder une base de données sous forme de champs de longueur fixe, on peut alors très bien opter pour un fichier binaire. Les enregistrements y seront certes placés séquentiellement sans que rien ne signale la jointure entre chaque enregistrement. Mais si on sait combien de bytes mesure invariablement chaque champ, on connaît donc la taille de chaque enregistrement. Et on peut donc très facilement récupérer les informations : si je sais que chaque enregistrement a une taille de 200 bytes, je lirai les bytes 1 à 200 pour le premier enregistrement, les bytes 201 à 400 pour le second, etc.

1. Les types d'accès

Au paragraphe précédent, nous avons vu que l’organisation des données au sein des enregistrements pouvait se faire selon deux grands choix stratégiques. Mais il existe une autre caractéristique importante dont il faut tenir compte : le type d’accès, autrement dit la manière dont la machine va aller rechercher les informations contenues dans le fichier.

On distingue notamment :

-L’accès séquentielOn ne peut accéder qu’à la donnée suivant celle qu’on vient de lire. On ne peut donc accéder à une information qu'en ayant au préalable lu toutes celles qui précèdent. Dans le cas d'un fichier texte, cela signifie qu'on lit le fichier ligne par ligne (enregistrement par enregistrement).

-L’accès indexéIl permet à la fois d'accéder directement à l’enregistrement de son choix en en précisant sa référence (cf. suite du cours) et de lire les enregistrements séquentiellement. Il est particulièrement adapté au traitement des gros fichiers, comme les bases de données importantes.

Pour conclure sur tout cela, voici un petit tableau récapitulatif :

 

Fichiers Texte

Fichiers Binaires

On les utilise pour stocker ...

des bases de données

tout, y compris des bases de données.

Ils sont structurés sous forme de ...

lignes (enregistrements)

Ils n'ont pas de structure apparente. Ce sont des bytes écrits à la suite les uns des autres.

Les données y sont écrites ...

exclusivement en tant que caractères

comme en mémoire RAM

Les enregistrements sont eux-mêmes structurés ...

au choix, avec un séparateur ou en champs de longueur fixe

en champs de longueur fixe, s'il s'agit d'un fichier d'enregistrements

Lisibilité

Le fichier est lisible clairement avec n'importe quel éditeur de texte

Le fichier a l'apparence d'une suite de caractères illisibles

Lecture du fichier

On ne peut lire le fichier que ligne par ligne

On peut lire les bytes de son choix (y compris la totalité du fichier d'un coup)

1. Les fichiers séquentiels

Un fichier séquentiel est donc une suite ordonnée d'enregistrements.

On parle d'accès séquentiel si on se limite à :

-Créer un fichier en fabriquant d'abord un fichier vide et en y ajoutant successivement des enregistrements selon l'ordre souhaité

-Relire les données du fichier en allant y rechercher les enregistrements un à un, dans l'ordre où ils y ont été placés, à partir du début du fichier.

Ces opérations pouvant bien évidemment être exécutées dans des programmes et moments différents.

Les opérations de base sont :

-L'ouverture du fichier : Lorsque l'on veut travailler avec un fichier, la première opération à effectuer est de l'ouvrir.Lorsque l'on exécute cette instruction, il faut notamment préciser le mode d'ouverture souhaité :- Lecture→On pourra uniquement lire les enregistrements les uns aprèsles autres sans modifier le fichier.- Ecriture→On ne pourra que créer des enregistrements. Attention, si lefichier n'était pas vide, toutes les anciennes données serontd'abord intégralement supprimées.- Ajout→On ne pourra qu'ajouter des nouveaux enregistrements à la findu fichier.C'est également lors de l'ouverture que le système crée un pointeur du programme vers le fichier. Ce dernier est positionné au début ou à la fin du fichier en fonction du mode d'ouverture ; et sera déplacé par la suite au sein du fichier au fur et à mesure des opérations effectuées par le programme.

-La lecture d'un enregistrement :Cette opération consiste à copier l'enregistrement actuellement désigné par le pointeur dans une variable du programme (généralement associée à un type structure) et à positionner le pointeur sur l'enregistrement suivant afin d'être prêt pour la lecture suivante.

-L'écriture d'un enregistrement :Cette opération consiste à écrire un enregistrement dans le fichier et à déplacer le pointeur à la position suivante afin d'être prêt pour l'écriture suivante.Pour rappel, l'écriture consiste toujours à ajouter un enregistrement à la fin du fichier séquentiel.

-Le test de fin de fichier (EOF ou End Of File) :Lorsque l'on lit un enregistrement, il faut toujours vérifier si la fin du fichier n'a pas été atteinte.Ce test diffère toutefois d'un langage à l'autre (voir tableau ci-après) :- Pour certains (ex.: le Cobol), la détection se fait lors de la lecture du fichier. Le système ne pouvant pas lire l'enregistrement attendu, il renvoie une erreur que le programme intercepte et traite correctement.- Pour d'autres (ex.: le Turbo-Pascal), la détection de fin du fichier doit être faite avant la lecture sans quoi l'erreur générée provoquera l'arrêt instantané du programme.- Pour d'autres (ex.: le Java), la détection se fait lors de la lecture du fichier. Le système ne pouvant pas lire l'enregistrement attendu, il renvoie une exception (= erreur). Cette exception provoque l'arrêt immédiat du bloc d'instructions en cours d'exécution. Ce bloc d'instructions doit donc avoir été écrit de telle manière qu'il puisse traiter cette exception. Si ce n'est pas le cas, tout le programme risque de s'arrêter.

-La fermeture du fichier :Cette commande ferme simplement le fichier.Attention, il faut toujours fermer soigneusement un fichier ouvert avant de quitter le programme !

Exemples de détection de fin de fichier :

Modèle Cobol

Modèle Turbo-Pascal

Modèle Java

ouvrir fichier;

...

lire (fichier, enreg);

répéter tant que !EOF

traitement enreg;

lire (fichier, enreg);

fin-répéter

...

fermer fichier;

ouvrir fichier;

...

répéter tant que !EOF

lire (fichier, enreg);

traitement enreg;

fin-répéter

...

fermer fichier;

ouvrir fichier;

...

try {

répéter tant que true

lire (fichier, enreg);

traitement enreg;

fin-répéter

}

catch IOException {}

...

fermer fichier;

Pour la suite du cours et les exercices, nous appliquerons la première méthode de détection de fin de fichier (→ Modèle Cobol).

Exemple :

Un fichier séquentiel (fichResult) contient les résultats des tests de tous les élèves de l'école. Il faut afficher, classe par classe, le total des points de chaque élève, ainsi que le nombre d'élèves qui ont réussi (total > 15).

Informations supplémentaires :

- Le fichier est trié par classe et, au sein d'une classe, sur le nom des élèves

- Le format d'un enregistrement est le suivant :- Classe (string)

- Nom élève (string)

- Points test 1 (réel)

- Points test 2 (réel)

- Points test 3 (réel)

Remarque :

On supposera que la conversion des points du format texte au format réel se fait automatiquement (Cette conversion se règle au niveau du langage de programmation et non de l'algorithme).

programme affichageResultats;

structstrEnreg :

classe : string;

eleve : string;

pts1 : réel;

pts2 : réel;

pts3 : réel;

fstruct

varenrResult : strEnreg;

classeTraitée : string;

total : réel;

nbrReussi : entier;

début

ouvrir fichResult;

lire (fichResult, enrResult);

répéter tant que !EOF

classeTraitée ← enrResult.classe;

nbrReussi ← 0;

écrire(écran, "Classe : ", classeTraitée);

répéter tant que (enrResult.classe = classeTraitée) et !EOF

total ← enrResult.pts1 + enrResult.pts2 + enrResult.pts3;

écrire(écran, enrResult.eleve, " : ", total);

si (total > 15)

alors nbrReussi ← nbrReussi + 1;

fin-si

lire (fichResult, enrResult);

fin-répéter

écrire(écran, "Résultat de la classe : ", nbrReussi);

fin-répéter

fermer fichResult;

fin

Remarquez dans cet exemple comment on a traité le changement de classe. Cette manière de travailler est très souvent utilisée dans les traitements de données séquentielles (de tableaux ou de fichier).

Exercice :

Faire l'exercice C6.

Les fichiers indexés et bases de données

1. Introduction

Une base de données (BD ou, en anglais, DB - database) est une entité dans laquelle on stocke des données de manière structurée. Ces données sont en fait contenues dans des fichiers indexés (ou tables). Chaque fichier est une sorte de tableau à deux dimensions contenant des informations sur un même sujet.

Avant d'aller plus loin dans ce chapitre, notons la différence entre une base de données logique et physique. Une base de données logique est composée de plusieurs fichiers séparés liés entre eux par les instructions écrites dans un programme ; chaque fichier devant être ouvert et traité par des instructions séparées. Une base de données physique regroupe directement toutes les tables entre-elles et il suffit d'ouvrir la DB pour que toutes les tables soient ouvertes ; chaque table pouvant être accédée séparément ou non.

Dans ce cours, je prendrai l'exemple d'une gestion d'une bibliothèque. On pourrait donc avoir une base de données qui contiendrait toutes les données sur les livres. Un des fichiers serait réservé aux livres eux-mêmes, alors que d'autres fichiers contiendraient les informations sur les lecteurs, etc.

On notera, à ce stade des explications, qu'il existe plusieurs logiciels de gestion de DB qui ont pour but de faciliter la manipulation des données. Ils permettent de créer un fichier, ajouter, supprimer, modifier,... rapidement des données, etc.

Mais avant de passer à cette étape d'encodage, il y a une autre étape à réaliser et cette dernière est peut-être la plus importante. Il s'agit de définir la structure des fichiers qui contiendront les données.

Pourquoi cette étape est-elle si importante ?Tout simplement parce que c'est à ce moment que l'on choisit les données à sauver, ainsi que la manière de les stocker. La qualité de la base de données dépendra donc fortement des choix opérés à cette étape. En effet, on ne pourra afficher que les informations que l'on a sauvées et que l'on peut retrouver facilement.

Un fichier contient généralement les informations sur un même sujet.

Ainsi le fichier "Livres" contiendra les informations sur les livres, mais pas sur les lecteurs :

Livres

Reference

Titre

Auteurs

TypeLivre

AnneeEdition

NbrExemplaires

M. Notion de liens entre les fichiers

Dans le cadre de l'informatisation de la gestion de la bibliothèque reprise dans notre exemple, on établit la liste des listes de contrôle que le bibliothécaire pourrait avoir besoin dans le futur. Un des souhaits possibles serait de pouvoir vérifier tous les livres empruntés depuis le début de l'année. Nous, informaticiens, devons-nous poser la question suivante : "Que faut-il comme informations dans la base de données pour pouvoir répondre à sa demande ?". La réponse est évidemment celle-ci : il faut un fichier reprenant tous les emprunts effectués depuis le début de l'année (voire depuis la création de la bibliothèque). La question découlant de cette réponse est : "Quels champs devons-nous y définir ?" Il faut, bien évidemment, retenir la date de l'emprunt, ainsi que les informations relatives au lecteur et au livre. Mais est-il nécessaire de sauver dans ce fichier toutes les données du lecteur et du livre ? Non, il suffit d'y retenir les références du lecteur et du livre ! En effet, toutes les autres données se trouvent déjà dans les autres fichiers de la base de données. Il nous suffit d'établir un lien entre les fichiers "Emprunts" et "Lecteurs", ainsi qu'un lien entre les fichiers "Emprunts" et "Livres" pour avoir toutes les informations nécessaires.

En d'autres mots, les liens entre les fichiers évitent d'avoir à répéter les informations d'un fichier dans un autre.

Précisons que le lien, physique ou logique, se fait grâce à un champ commun qui est une clé primaire dans l'un des deux fichiers.

1. Les fichiers indexés

Si nous prenons comme exemple le fichier "Lecteurs" et que nous recherchons les informations concernant une personne précise, cela peut prendre beaucoup de temps si les données ne sont pas triées. En effet, si rien n'est précisé, le système classe les informations dans l'ordre suivant lequel on les a encodées. Par contre, si on lui a demandé de trier les données sur le champ Nom, on retrouvera les informations de la personne voulue très rapidement.

Un problème subsiste toutefois. En effet, comment faire si deux personnes ont le même nom ? Pour contourner ce problème, les informaticiens ont défini la notion de clé primaire.

Une clé primaire est une zone (ou un ensemble de zones) qui joue trois rôles :

-Le premier est d'assurer une identification unique de chaque enregistrement du fichier.

-Le deuxième est de préciser l'ordre suivant lequel les données seront triées.

-Le troisième consiste à établir des liens entre les divers fichiers de la base de données.

Dans l'exemple "Livres", le champ "Reference" sera utilisé comme clé primaire. Cette référence sera définie comme étant unique et ne sera donc jamais attribuée à deux livres.

Si une clé primaire est souvent indispensable pour tous les fichiers, elle n'est toutefois pas suffisante. En effet, il ne faut pas oublier que le rôle principal d'une clé primaire est d'identifier de manière unique un enregistrement dans un fichier. C'est pour cette raison que l'on attribue généralement une référence (numérique ou autre) à chaque enregistrement ; référence qui sert de clé primaire. Mais qu'arrive-t-il lorsque l'on recherche un enregistrement dont on ne connaît pas cette référence ? Il suffit alors, simplement, de rechercher l'enregistrement en comparant le contenu d'autres champs (ex.: le nom d'une personne ou le titre d'un livre)... Le problème, c'est que dans ce cas, le système doit lire tous les enregistrements du fichier pour trouver celui que l'on a demandé. Ce qui peut prendre beaucoup de temps. Pour éviter cette perte de temps, on va créer un index sur les champs des fichiers que l'on utilisera lors des recherches. On pourrait donc indexer un champ "Ville" pour retrouver rapidement tous les clients de Bruxelles.

Attention, contrairement à la clé primaire, les index supplémentaires autorisent les doublons (= valeur identique pour deux enregistrements).

1. Les opérations de base

Attention, certaines opérations dépendent fortement du système de gestion de base de données utilisé. Les informations données ci-après ne seront donc que générales et devront être adaptées en fonction du système utilisé.

Les opérations de base sont :

-L'ouverture de la base de données physique : Lorsque l'on veut travailler avec une DB complète, la première opération à effectuer est de l'ouvrir.Syntaxe : ouvrir (DB)

-L'ouverture du fichier : Lorsque l'on veut travailler avec un fichier, la première opération à effectuer est de l'ouvrir.Lorsque l'on exécute cette instruction, il faut notamment préciser le mode d'ouverture souhaité :- Input→On pourra uniquement lire les enregistrements sans modifierle fichier.- Output→On ne pourra que créer des enregistrements. Attention, si lefichier n'était pas vide, toutes les anciennes données serontd'abord intégralement supprimées.- In/Out→On pourra effectuer toutes les opérations souhaitées (lire,modifier, ajouter, supprimer des enregistrements).Certains systèmes exigeront aussi que l'on indique l'index à utiliser ; d'autres systèmes rechercheront par eux-mêmes l'index à utiliser lors des commandes de lecture.C'est également lors de l'ouverture que le système crée un pointeur du programme vers le fichier. Mais attention, dans ce type de fichier, le pointeur n'est positionné sur aucun enregistrement en particulier lors de l'ouverture du fichier.Syntaxe : ouvrir (fichier, mode, index)

-La lecture directe d'un enregistrement :Cette opération consiste à rechercher, via un index, l'enregistrement correspondant à la demande et à le copier en mémoire.Pour permettre cette lecture, il faut bien évidemment indiquer les critères de recherche (ex.: Reference = "ABC123").Syntaxe : lire (fichier, 'IND' + index, critères, enreg)

-La lecture séquentielle d'un enregistrement :Cette opération consiste à déplacer le pointeur sur l'enregistrement suivant et le copier en mémoire.Attention, certains systèmes exigent que l'on exécute, avant la première lecture séquentielle, une autre commande (Start) afin de positionner le pointeur avant le premier enregistrement à lire. Cette dernière permet notamment d'indiquer les critères de recherche du premier enregistrement à traiter.Syntaxe : lire (fichier, 'START' + index, critères)Syntaxe : lire (fichier, 'SEQ', enreg)

-La lecture globale de plusieurs enregistrements (via les commandes SQL) :Cette opération consiste à rechercher et copier dans un tableau en mémoire tous les enregistrements qui répondent aux critères de sélection.Lors de cette opération, on peut également souvent indiquer l'ordre suivant lequel on souhaite que le système trie les enregistrements avant de les copier dans le tableau.Cette commande permet généralement aussi de fusionner des informations venant de plusieurs tables.Syntaxe : lire (DB, 'SQL', requête, tableau)

-L'écriture d'un enregistrement :Cette opération consiste à écrire un enregistrement dans le fichier. Syntaxe : écrire (fichier, enreg)

-La modification d'un enregistrement :Cette opération consiste à modifier un enregistrement dans le fichier.Attention, certains systèmes exigent au préalable une lecture directe de l'enregistrement en question avec le paramètre de blocage actif. Ce paramètre indique au système qu'il doit veiller à ce que notre programme soit le seul à pouvoir momentanément modifier ou supprimer cet enregistrement. Ce blocage sera désactivé automatiquement lors de la commande de mise à jour de l'enregistrement.La modification consiste donc à lire dans un premier temps l'enregistrement, le modifier en mémoire, puis à le réécrire dans le fichier. Syntaxe : lire (fichier, 'BLOCK' + index, critères, enreg)Syntaxe : réécrire (fichier, enreg)

-La modification globale de plusieurs enregistrements (via SQL) :Cette opération utilisant une requête SQL (ou query) consiste à rechercher et modifier tous les enregistrements qui répondent aux critères de sélection.Syntaxe : réécrire (DB, 'SQL', requête)

-La suppression d'un enregistrement :Cette opération consiste à supprimer définitivement un enregistrement du fichier.Attention, certains systèmes exigent au préalable une lecture directe de l'enregistrement en question avec le paramètre de blocage actif.La suppression consiste donc à lire, si nécessaire, l'enregistrement pour le bloquer, puis à le supprimer du fichier. Syntaxe : lire (fichier, 'BLOCK' + index, critères, enreg)Syntaxe : supprimer (fichier, enreg)

-La suppression globale de plusieurs enregistrements (via SQL) :Cette opération utilisant une requête SQL consiste à rechercher et supprimer tous les enregistrements qui répondent aux critères de sélection.Syntaxe : supprimer (DB, 'SQL', requête)

-Le test de lecture erronée (EOF ou enregistrement non trouvé) :Lorsque l'on lit un enregistrement séquentiellement, il faut toujours vérifier si la fin du fichier n'a pas été atteinte.De même, on doit vérifier si on a atteint la fin du tableau lorsqu'on traite les enregistrements copiés après une lecture globale.Il faut également vérifier si le système a trouvé l'enregistrement demandé lors d'une lecture directe. Syntaxe : Il faut tester les erreurs EOF et IOError.

-La fermeture du fichier :Cette commande ferme simplement le fichier.Attention, il faut toujours fermer soigneusement un fichier ouvert avant de quitter le programme ! Syntaxe : fermer (fichier)

-La fermeture de la DB :Cette commande ferme simplement la DB.Syntaxe : fermer (DB)

Exercice :

Faire l'exercice C7.