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

Algorithmes et programmation en Pascal


précédentsommairesuivant

V. Tableaux

Les tableaux permettent de manipuler plusieurs informations de même type, de leur mettre un indice : la 1ère info, la 2ème info,..., la ième info, . . .

Ils sont stockés en mémoire centrale comme les autres variables, contrairement aux fichiers qui sont stockés sur le disque.

Une propriété importante des tableaux est de permettre un accès direct aux données, grâce à l'indice.

On appelle souvent vecteur un tableau en une dimension.

V-1. Le type array

V-1-1. Principe

Syntaxe

 
Sélectionnez
array [ I ] of T

I étant un type intervalle, et T un type quelconque.

Ce type définit un tableau comportant un certain nombre de cases de type T , chaque case est repérée par un indice de type I.

Exemple

 
Sélectionnez
TYPE vec_t = array [1..10] of integer;
VAR v : vec_t;

v est un tableau de 10 entiers, indicés de 1 à 10.

representation en moire tableau
  • À la déclaration, le contenu du tableau est indéterminé, comme toute variable.
  • On accède à la case indice i par v[i] (et non v(i)).
  • Pour mettre toutes les cases à 0 on fait
 
Sélectionnez
for i := 1 to 10 do
 v[i] := 0;

Remarque : L'intervalle du array peut être de tout type intervalle, par exemple 1..10, 'a'..'z', false..true, ou encore un intervalle d'énumérés Lundi..Vendredi.

On aurait pu déclarer vecteur comme ceci (peu d'intérêt) :

 
Sélectionnez
TYPE interv = 1..10 ; 
vec_t = array [ interv ] of	integer;

V-1-2. Contrôle des bornes

Il est en général conseillé de repérer les bornes de l'intervalle avec des constantes nommées : si on décide de changer une borne, cela est fait à un seul endroit dans le programme.

L'écriture préconisée est donc

 
Sélectionnez
CONST vec_min = 1;
      vec_max = 10;
TYPE vec_t = array[vec_min..vec_max] of integer;

Règle 1

Il est totalement interdit d'utiliser un indice en dehors de l'intervalle de déclaration, sinon on a une erreur à l'exécution.

Il faut donc être très rigoureux dans le programme, et ne pas hésiter à tester si un indice i est correct avant de se servir de v[i].

Exemple : Programme demandant à rentrer une valeur dans le vecteur.

 
Sélectionnez
CONST vec_min = 1;
      vec_max = 10;
TYPE vec_t = array[vec_min..vec_max] of integer;
VAR v : vect_t;
    i : integer;
BEGIN
  write ('i ? ');
  readln(i);
  if (i  >=  vec_min) and  (i  <=  vec_max) then
  begin
	write  ('v[',  i,  ']  ?  ');
	readln(v[i]);
  end
  else
	writeln('Erreur, i  hors  intervalle  ', vec_min,  '..',  vec_max);
END.

Règle 2

Le test d'un indice i et de la valeur en cet indice v[i] dans la même expression sont interdits.
Exemple :

 
Sélectionnez
if  (i  >=  vec_min) and  (i  <=  vec_max) and  (v[i]  <>  -1)  then
   ... 
else
   ...;

Une expression est toujours évaluée en intégralité; donc si (i <= vec_max), le test (v[i] <> -1) sera quand même effectué, alors même que l'on sort du vecteur ! Solution : séparer l'expression en 2.

 
Sélectionnez
if  (i  >=  vec_min) and  (i  <=  vec_max) then
   if  (v[i]  <>  -1)  then 
     ...
   else
     ...
else
    ...  {  erreur hors  bornes  }  ;

V-1-3. Recopie

En Pascal, la seule opération globale sur un tableau est : recopier le contenu d'un tableau v1 dans un tableau v2 en écrivant : v2 := v1;

Ceci est équivalent (et plus efficace) que

 
Sélectionnez
for  i  :=  vec_min  to  vec_max  do
  v2[i]  :=  v1[i];

Il y a une condition : les 2 tableaux doivent être exactement de mêmes types, i.e issus de la même déclaration.

 
Sélectionnez
TYPE vecA  =  array  [1..10]  of  char;
     vecB  =  array  [1..10]  of  char;
VAR v1  :  vecA;
	v2  :  vecA;
	v3  :  vecB;
BEGIN 
  v2  :=  v1;	{  legal  car  meme  type  vecA  }
  v3  :=  v1;	{  illegal, objets  de  types  <>  vecA  et  vecB  }

V-2. Super tableaux

Quelques types un peu plus complexes à base de tableaux, et de combinaisons entre types.

V-2-1. Tableaux à plusieurs dimensions

Exemple : dimension 1 = vecteur ; dimension 2 = feuille excel ; dimension 3 =classeur excel. On peut créer des tableaux à plusieurs dimensions de plusieurs manières :

  • v1 : array [1..10] of array [1..20] of real -> Tableau de 10 éléments, chaque élément étant un tableau de 20 réels. On accède à l'élément d'indice i dans 1..10 et j dans 1..20 par v1[i][j].
  • v2 : array [1..10, 1..20] of real -> Tableau de 10 * 20 réels. On accède à l'élément d'indice i dans 1..10 et j dans 1..20 par v2[i,j].
Exemple Mise à 0 du tableau v2
Sélectionnez
VAR v2  :  array  [1..10,  1..20]  of  real;
    i,  j  :  integer;
BEGIN 
 for  i  :=  1  to  10  do 
    for  j  :=  1  to  20  do
      	v2[i,j]  :=  0.0;  
END.

V-2-2. Tableaux de record

On peut créer des tableaux d'enregistrements, et des enregistrements qui contiennent des tableaux.

 
Sélectionnez
PROGRAM Ecole; 
  CONST MaxEleves  =  35; 
        MaxNotes	=  10;
  TYPE note_t  =  array  [1..MaxNotes] of  real; 
       eleve_t  =  Record
                    age,  nb_notes  :  integer; 
                    notes  :  note_t; 
                    moyenne  :  real; 
                  End; 
	   classe_t  =  array  [1..MaxEleves] of  eleve_t;
  VAR c  :  classe_t; 
	  nb_eleves, i,  j  :  integer; 
BEGIN
   {  ...  } 
for  i  :=  1  to  nb_eleves do 
  begin
    writeln  ('Eleve n.',  i); 
    writeln  ('   age	:  ',  c[i].age);
    write	('   notes  :');
    for  j  :=  1  to  c[i].nb_notes do
      write  ('  ',  c[i].notes[j]);
    writeln;
	writeln  ('   moy	:  ',  c[i].moyenne);
   end;
END.
  • On a comme d'habitude le droit de faire une copie globale entres variables du même type :
 
Sélectionnez
VAR  c1,  c2  :  classe_t; 
    e  :  eleve_t;   
    i,  j  :  integer; 
BEGIN
  {  copie  globale de  type  classe_t  } 
  c2  :=  c1; {  échange  global de  type  eleve_t  } 
  e  :=  c1[i];  
  c1[i]  :=  c1[j]; 
  c1[j]  :=  e; 
END.
  • Exemple de passages de paramètres : on écrit une procédure affichant un eleve_t.
 
Sélectionnez
PROCEDURE affi_eleve  (e  :  eleve_t); 
 VAR  j  :  integer; 
BEGIN 
  writeln  ('   age	:  ',  e.age);
  write	('   notes  :  ');
  for  j  :=  1  to  e.nb_notes do  
	  write  (e.notes[j]);
  writeln;
  writeln('   moy	:  ',  e.moyenne);
END;	
BEGIN 
 {  ...  }
 for  i  :=  1  to  nb_eleves do
 begin 
   writeln('Eleve n.',  i);
   affi_eleve  (c[i]);
   end; 
 END.

affi_eleve(e) ne connait pas le numéro de l'élève ; l'appelant, lui, connait le numéro, et l'affiche avant l'appel.

On peut encore écrire une procédure affi_classe :

 
Sélectionnez
PROCEDURE affi_classe  (c  :  classe_t  ;  nb  :  integer);
  VAR  i  :  integer; 
BEGIN 
 for  i  :=  1  to  nb  do
 begin
   writeln  ('Eleve n.',  i); 	
   affi_eleve  (c[i]);  
   end; 
END; 
BEGIN
  {  ...  } 
  affi_classe  
  (c,  nb_eleves);
END.

V-3. Le type string

On code une chaîine de caractère telle que 'bonjour' dans un objet de type string.

V-3-1. Principe

Syntaxe :

string [m] où m est une constante entière donnant le nombre maximum de caractères pouvant être mémorisés. Exemple :

 
Sélectionnez
  VAR  s  :  string[80]; 
BEGIN
 s  :=  'Le  ciel  est  bleu.'; 
 writeln  (s); 
END.

Codage

Ayant déclaré s : string[80], comment sont codés les caractères ?
En interne, Pascal réserve un array [0..80] of char.
Le premier caractère est s[1], le deuxième est s[2], etc.
La longueur courante de la chaîne est codé dans la case 0 (-> ord(s[0])).

Remarque

  • Affecter une chaîne plus longue que l'espace réservé à la déclaration est une erreur.
  • Comme la longueur courante est codée sur un char, elle est limitée à 255.

V-3-2. Opérateurs sur les strings

a := '' Chaîne vide (longueur 0).
a := b Recopie de b dans a.
a := c + d Concaténation en une seule chaîne. c et d de types string ou char ; le résultat est un string.
length(a) : Longueur courante de a, résultat entier.

 
Sélectionnez
  CONST   Slogan  =  'lire  la  doc';
  VAR     s1,  s2  :  string[100];
          i  :  integer;
BEGIN
 s1  :=  'veuillez  ';
 s2  :=  s1  +  Slogan; 
 writeln('s2  =  ''',  s2,  ''''); 
 writeln('Longueur courante de  s2  :  ',  length(s2)  ); 
 write  ('Indices des  ''l''  dans  s2  :  '); 
 for  i  :=  1  to  length(s2) do 
   if  s2[i]  =  'l'  then  
      write(i,  '  '); 
 writeln; 
END.

Comparaison entre 2 string : les opérateurs =, <>, <, >, < =, >=, sont utilisables, etle résultat est un booléen.

La comparaison se fait selon l'ordre lexicographique du code ASCII.
Exemple : Soit b un booléen ; b est-il vrai ou faux ?

 
Sélectionnez
b  :=  'A  la  vanille'  <  'Zut';{  vrai  }
b  :=  'bijou'  <  'bidon';{  faux,  c'est  >  car  'j'  >  'd'  }
b  :=  'Bonjour'  =  'bonjour';	{  faux,  c'est  <  car  'B'  <  'b'  }
b  :=  '  zim  boum'  >  'attends  !';	{  faux,  c'est  <  car  '  '  <  'a'  }

Exercice : On considère le type LongString suivant.

 
Sélectionnez
CONST longStringMax  =  4096;
TYPE   LongString  =  record;
                       c  :  array  [1..LongStringMax] of  char;
		               l  :  interer;  {  longueur courante  }  
                      end;

Écrire les procédures et fonctions suivantes :

 
Sélectionnez
FUNCTION longueur(s1  :  LongString  )  :  integer;
FUNCTION est_inferieur  (s1,  s2  :  LongString  )  :  boolean; 
FUNCTION est_egal  (s1,  s2  :  LongString  )  :  boolean; 
PROCEDURE concatene  (s1,  s2  :  LongString  ; var  s3  :  LongString);

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.