IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Algorithmes et programmation en Pascal


précédentsommairesuivant

VI. Fichiers séquentiels

Les entrées/sorties dans un ordinateur sont la communication d'informations entre la mémoire de l'ordinateur et ses périphériques (disques, clavier, écran, imprimante, etc).

Les entrées/sorties se font par le biais de fichiers séquentiels.

Un fichier séquentiel est une collection de données de même type (souvent de caractères), dans laquelle les donnèes ne peuvent être lues ou écrites que les unes après les autres, en commençant par le début et sans retour possible en arrière.

Un fichier peut être vide ; il peut avoir une fin ou non ; il peut être ouvert (accessible) ou fermé ; une lecture peut être << en attente > >.

VI-1. Le clavier et l'écran

Le clavier et l'écran sont gérés comme des fichiers particuliers : ce sont des fichiers texte, toujours ouverts et sans fin; ils sont désignés par les variables prédéfinies input et output (dont on ne se sert quasiment jamais).

VI-1-1. Affichage avec write

La procédure write() permet d'afficher un ou plusieurs paramètres. writeln() fait la même chose puis rajoute un saut de ligne.

Trois ecritures equivalentes :

 
Sélectionnez
writeln (a, b, c, d);
write (a, b, c, d); writeln;
write(a); write(b); write(c); write(d); writeln;
  • Le résultat de l'affichage dépend du type du paramètre :
 
Sélectionnez
VAR  e  :  integer;
     c  :  char;  
     b  :  boolean;
     r  :  real; 
     s  :  string[32]; 
 BEGIN 
  e  :=  12;  
  c  :=  'A';  
  b  :=  true;  
  r  :=  23.0;  
  s  :=  'toto'; 	
  writeln  (e,  '|',  c,  '|',  b,  '|',  r,  '|',  s);  
END.

affiche : 12|A|TRUE|2.300000E+01|toto

Formatter l'impression des variables
  • Soit v un entier, un booléen, un caractère ou un string. write(v:8) dit à write d'afficher v sur au moins 8 caractères. Si le nombre de caractères (signe éventuel compris) est > 8, v est complètement affiché ; si il est < 8, des espaces sont rajoutés à gauche pour compléter. .
 
Sélectionnez
writeln  (e:5,  '|',  c:3,  '|',  b:5,  '|',  s:6);

Ainsi affiche : ___12|___A|_TRUE|__toto

  • Soit r un réel.
    write(r:10); dit à write d'afficher r en notation scientifique, sur au moins 10 caractères, signes de la mantisse et de l'exposant compris.
    Cette fois c'est d'abord le nombre de chiffres après la virgule qui change de 1 à 10, puis au besoin des espaces sont ajoutés à gauche.
    De plus le dernier chiffre de la mantisse affichée est arrondi.
 
Sélectionnez
r  :=  2  /  3; 	
writeln  (r:8,  '|',  r:10,  '|',  r:18  );

affiche : _6.7E-01|_6.667E-01|__6.6666666667E-01

Autre formattage de r réel
  • write(r:8:4); dit à write d'afficher r en notation simple, sur au moins 8 caractères, dont 4 chiffres après la virgule (le dernier étant arrondi).
    Ainsi writeln (r:8:4);
    affiche : __0.6667
Bilan
  • Le formattage permet d'aligner des chiffres.
  • Ne pas oublier de mettre des espaces autour des variables pour que le résultat ne soit pas tout aglutiné et illisible.
  • On ne peut afficher que des types simples.

VI-1-2. Lecture avec read

La procédure read() permet de lire un ou plusieurs paramètres. readln() fait la même chose puis fait un readln;

Trois écritures équivalentes :

 
Sélectionnez
readln  (a,  b,  c,  d); 
read  (a,  b,  c,  d);  readln; 
read(a); read(b); read(c); read(d); readln;
Remarques
  • À l'exécution d'une de ces lignes, on peut rentrer les données en les séparant par des espaces, des tabulations ou des retours chariot Image non disponible
  • Il faut que les données lues correspondent au type attendu de chaque variable, sinon il y a une erreur à l'exécution.

Le comportement de read() et readln; étant complexe, regardons plus en détail se qui se passe à l'exécution.

  • L'utilisateur tape une série de caractères, avec de temps à autres des retours chariot Image non disponible
  • Pendant la frappe, les caractères sont stockés dans un buffer (une mémoire tampon) ; à chaque Image non disponible , le contenu du buffer est envoyé au programme Pascal (y compris le Image non disponible ).
  • De son côté, read(v); lit une donnée dans le buffer, ou attend le buffer suivant. Le read(v); attend donc quand
    - on n'a pas tapé de Image non disponible ,
    - ou qu'on a tapé une ligne vide,
    - ou que toutes les données dans le buffer ont déjà été lues.
  • readln; attend le prochain Image non disponible, puis vide le buffer. Attention les données non lues dans le buffer sont alors perdues pour de futurs read().
Exemple
Sélectionnez
VAR  a,  b,  c,  d  :  integer; 
BEGIN 
readln  (a,  b);	{  =  read(a); read(b); readln;  }
readln  (c,  d);
writeln  ('Lu  :  ',  a,  '  ',  b,  '  ',  c,  '  ',  d); 
END.
Essais : 1 Image non disponible
2 Image non disponible
3 Image non disponible
4 Image non disponible
Lu : 1 2 3 4
1 2Image non disponible
3 4Image non disponible
Lu : 1 2 3 4
1 2 3Image non disponible
4 5 6Image non disponible
3 et 6 perdus


Le même programme avec read (a, b, c, d); readln;

Produit : 1 Image non disponible
2 Image non disponible
3 Image non disponible
4 Image non disponible
Lu : 1 2 3 4
Idem
1 2Image non disponible
3 4Image non disponible
Lu : 1 2 3 4
Idem
1 2 3Image non disponible
4 5 6Image non disponible
5 et 6 perdus

Remarque

Le type des objets lus a une grande importance pour read(). Dans notre programme exemple, voici ce qui se passe si on déclare les 4 variables en char :

VAR a, b, c, d : integer; 1 2 3 4 Image non disponible
Lu : 1 2 3 4
VAR a, b, c, d : char; 1 2 3 4 Image non disponible
Lu : 1 _ 2 _

Remarque

On ne peut faire un read() que sur un entier, un réel, un caractère ou une chaîne de caractères ; on ne peut pas faire un read() sur un booléen.
Algorithme de lecture d'une suite de caractères tapés au clavier, se terminant par un '.'

Option : on affiche le code ASCII de chaque caractère.

 
Sélectionnez
CONST CarFin = '.';
VAR c : char;
BEGIN
read(c); { premier caractère }
while c <> CarFin do
begin
writeln (c, ' ', ord(c)); { option }
read(c); { caractère suivant }
end; { lu à la fin du while }
readln; { vide buffer et retour chariot }
END.
Exécution : SalutImage non disponible
S 83
a 97
l 108
u 117
t 116
13
10
Ciao.byeImage non disponible
C 67
i 105
a 97
o 111

VI-2. Fichiers de disque

Les fichiers de disque permettent de stocker des informations de manière permanente, sur une disquette ou un disque dur.

Ces informations persistent même lorsque l'ordinateur est éteint.

L'inconvénient est que ces données ne sont pas en mémoire vive ; on n'y accède pas directement, comme c'est le cas avec un vecteur.

En fait on va lire ou écrire des données une à une sur le disque, étant donné qu'il s'agit de fichiers séquentiels.

VI-2-1. Notions générales

Sur un disque, un fichier a un nom, par exemple 'a :\mass\tp4.pas'
On peut coder ce nom dans un string, par exemple nomf.

Dans un programme qui doit manipuler ce fichier, il faut une variable pour le désigner, par exemple f.

Déroulement des opérations
  1. Déclarer la variable f
    f : text ; ou f : file of qqchose ;
  2. Assigner la variable f au fichier de nom nomf
    assign (f, nomf) ;
  3. Ouvrir le fichier f pour pouvoir y lire ou y écrire les données
    reset (f) ; ou rewrite (f) ;
  4. Lire ou écrire des données
    read (f, donnee) ; ou write (f, donnee) ;
  5. Quand on a fini, on ferme le fichier
    close (f) ;

Lecture ou écriture

On ouvre un fichier soit en lecture, soit en écriture. On ne peut pas faire les deux en même temps.

  • En lecture : on fait reset(f); puis des read(f, ...); Si le fichier n'existe pas, il y a une erreur.
  • En écriture : on fait rewrite(f); puis des write(f, ...); Si le fichier n'existe pas, un rewrite le crée. Si il existe déjà, le rewrite l'écrase, c'est-à-dire que l'ancien contenu est définitivement perdu.

Fin du fichier

En lecture, avant de faire un read, il faut tester si il y a encore quelque chose à lire ; on n'a pas le droit de faire un read si la fin du fichier est atteinte.
La fonction eof(f) retourne true si la fin du fichier est atteinte.

Deux familles de fichiers

On distingue les fichiers de texte des fichiers d'éléments.

VI-2-2. Fichiers de texte

Les fichiers de textes sont les fichiers que vous pouvez éditer, comme par exemple vos fichiers pascal.

Déclaration
Sélectionnez
VAR 
      f  :  text; 
      c  :  char; 
      s  :  string[255]; 
      x  :  integer; 
      r  :  real;

Lecture

  1. read (f, c); lit un caractère dans f.
  2. readln (f, s); lit une ligne complète dans f (toujours readln sur un string).
  3. read (f, x); lit un entier dans f. On peut de la même manière lire un réel.

Écriture

  1. write (f, c) ; écrit un caractère dans f.
  2. write (f, s); écrit le string dans f. Pour passer à la ligne on fait writeln(f);
  3. read (f, x); lit un entier dans f. On peut de la même manière lire un réel.
  4. write (f, x, ' '); écrit un entier dans f. On peut de la même manière écrire un réel ou un booléen. Il vaut mieux rajouter un espace (ou un retour chariot) après chaque donnée pour que lors d'une relecture ultérieure, les données ne soit pas accolées en un bloc illisible.
  5. write (f, r:8:2); écrit un réel formatté dans f.

Morale

En lecture comme en écriture, la manipulation des fichiers texte se passe très naturellement, de la même façon que la lecture au clavier ou l'écriture à l'écran.

Tous les algorithmes de lecture vus en TD (Horner, compter les 'LE') sont directement applicables sur les fichiers texte.

En fait, le clavier et l'écran sont tout simplement considérés comme des fichiers texte, les fichiers input et output.

VI-2-3. Fichiers d'élements

Les fichiers d'éléments sont des copies de la mémoire vive, les éléments étant tous du même type.

Le type d'élément peut être un type simple, un enregistrement, un tableau, etc.

Déclaration
Sélectionnez
TYPE element_t = record
                  age : integer;
                  majeur : boolean;
                 end;
VAR f : file of element_t;
    e : element_t;

Lecture

read (f, e); lit un élément dans f. On ne fait jamais de readln.

Écriture

write(f, e); écrit un élément dans f. On ne fait jamais de writeln.

Schémas types

write(f, e); écrit un élément dans f. On ne fait jamais de writeln.

  • Mettre un vecteur vec de nb éléments dans un fichier.
 
Sélectionnez
VAR
    vec : array [1..vmax] of element_t;
    nb, i : integer;
BEGIN
  assign (f, nomf);
  rewrite (f);
  for i := 1 to nb do
  write (f, vec[i]);
  close (f);
END;
  • Opération inverse ; on ne connait pas nb au départ.
 
Sélectionnez
BEGIN
  assign (f, nomf);
  reset (f);
  nb := 0;
  while not eof(f) and (nb < vmax) do
  begin nb := nb+1; read(f, vec[nb]); end;
  close (f);
END;
VI-2-4. Gestion des erreurs

L'ouverture d'un fichier peut provoquer une erreur, qui plante le programme. Par exemple, si on veut ouvrir un fichier en lecture, ce fichier doit exister. Si on veut créer un fichier, le chemin du fichier doit être valide.

Chaque compilateur fournit sa propre méthode pour éviter un plantage. Sous Delphi et sous Turbo Pascal, on encadre reset ou rewrite entre 2 options de compilations spéciales :

{$I-} désactive temporairement le contrôle des entrées/sorties
{$I+} le rétablit.

Juste après on regarde si il y a eu une erreur en testant la variable IoResult.

Exemple En écriture
Sélectionnez
BEGIN
  assign (f, nomf);
  {$I-} rewrite (f); {$I+}
  ok := IoResult = 0;
  if not ok
  then writeln ('Erreur création fichier ', nomf)
  else begin
  ...
  write (f, ...);
  ...
  close (f);
end;
END;
Exemple En lecture
Sélectionnez
BEGIN
  assign (f, nomf);
  {$I-} reset (f); {$I+}
  ok := IoResult = 0;
  if not ok then 
   writeln ('Erreur lecture fichier ', nomf) 
  else
   begin
    ...
   while not eof(f) do
   begin
    read (f, ...);
   ...
   end;
  ...
  close (f);
 end;
END;

Remarque

On peut aussi utiliser IoResult dans la lecture au clavier, en encadrant read entre {$I-} et {$I+}. Par exemple lorsqu'on attend un réel et qu'une lettre est tapée, le programme, au lieu de planter, détectera l'erreur et pourra redemander une frappe.


précédentsommairesuivant

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2010 Edouard Thiel. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.