Aller au contenu principal

Les tableaux

Ce que ce chapitre apporte

  • Déclarer un tableau, lire et écrire une case par son indice, de 0 à Size(t) - 1.
  • Reconnaître un indice hors du tableau et dire ce que l'exécution en fait.
  • Parcourir un tableau avec une boucle For pour accumuler, compter et chercher.
  • Trouver le maximum d'une série et l'indice où il se trouve.
  • Lire un texte caractère par caractère avec Len et Char, dont les indices suivent la même règle.

Un capteur qui relève le niveau d'une cuve toutes les heures produit 24 valeurs par jour. Les ranger dans 24 variables rendrait le programme illisible, et passer à un relevé toutes les demi-heures obligerait à tout réécrire. Le tableau range la série entière sous un seul nom, et une boucle la parcourt. Ce chapitre montre comment déclarer un tableau, atteindre une case par son indice, et faire le tour de la série pour accumuler, compter ou chercher.

Ranger une série de valeurs dans un tableau

Vingt-quatre relevés horaires, ce ne sont pas vingt-quatre variables releve0, releve1, releve2, etc. Chacune demanderait sa propre forme de saisie, sa propre ligne dans chaque calcul, et passer à un relevé toutes les demi-heures obligerait à tout réécrire.

Définition

Un tableau est une variable qui contient plusieurs valeurs du même type. Il se déclare avec une taille, le nombre de ses cases. Chaque case est désignée par son indice, écrit entre crochets : les indices vont de 0 à taille - 1. Un tableau de 4 cases va de debits[0] à debits[3]. La fonction intégrée Size(debits) rend le nombre de cases.

Organigramme, tel que l'affiche Flowgorithm
Exécuter comme dans Flowgorithm, en continu ou forme par forme.
MainReal Array debits[4]debits[0] = 12.5debits[1] = 14debits[2] = 9.5debits[3] = 11Output "Débit à l'indice 2 : " & debits[2] & " L/min"Output "Nombre de cases : " & Size(debits)End

Quatre débits de pompe rangés sous un seul nom. La déclaration porte la taille ; chaque affectation vise une case par son indice.

Dérouler ce programme en pas à pas : juste après la déclaration, la fenêtre des variables affiche debits[0] à debits[3], encore vides, puis chaque affectation remplit une case. Le programme affiche Débit à l'indice 2 : 9.5 L/min, c'est-à-dire la troisième valeur rangée, puis Nombre de cases : 4.

Le premier élément est à l'indice 0

debits[2] n'est pas le deuxième débit mais le troisième. La dernière case d'un tableau de 4 cases porte l'indice 3, et debits[4] n'existe pas. Pour désigner la dernière case sans compter, écrire debits[Size(debits) - 1].

Parcourir un tableau

Un indice n'est pas forcément un nombre écrit en dur : c'est une expression, et le plus souvent la variable d'une boucle For. La boucle pour i de 0 à Size(t) - 1 passe par toutes les cases, dans l'ordre, et le même programme reste juste si la taille du tableau change.

Organigramme, tel que l'affiche Flowgorithm
Exécuter comme dans Flowgorithm, en continu ou forme par forme.
NextDoneFalseTrueFalseTrueNextDoneMainReal Array temperatures[6]Integer i, depassements, indicePicReal sommei = 0 to Size(temperatures) - 1Input temperatures[i]somme = 0depassements = 0indicePic = 0i = 0 to Size(temperatures) - 1somme = somme + temperatures[i]temperatures[i] > 30depassements = depassements + 1temperatures[i] > temperatures[indicePic]indicePic = iOutput "Moyenne : " & ToFixed(somme / Size(temperatures), 1) & " °C"Output "Relevés au-dessus de 30 °C : " & depassementsOutput "Pic : " & temperatures[indicePic] & " °C à l'indice " & indicePicEnd

Six températures d'un local technique. Une première boucle remplit le tableau ; une seconde le parcourt pour accumuler, compter et chercher le pic.

Avec les saisies proposées, le programme affiche Moyenne : 25.9 °C, Relevés au-dessus de 30 °C : 2 et Pic : 33.5 °C à l'indice 4. En pas à pas, la forme somme ← somme + temperatures[i] s'exécute 6 fois, une par case, et la fenêtre des variables montre i qui désigne la case lue. Changer une saisie, par exemple 33.5 en 29, puis observer le compteur et le pic.

TraitementAvant la boucleDans la boucle
Accumuler (somme, moyenne)somme ← 0somme ← somme + t[i]
Compternb ← 0nb ← nb + 1, seulement si la condition est vraie
Chercher le maximumindicePic ← 0, la première caseindicePic ← i si t[i] dépasse la case retenue

Pour le maximum, retenir l'indice plutôt que la valeur donne les deux à la fois : la valeur se relit dans la case. L'affectation indicePic ← i s'exécute ici 4 fois, chaque fois qu'une température dépasse la case retenue. Partir de la première case, et non d'une valeur choisie comme 0, garantit que le résultat est une valeur réellement présente dans le tableau.

Organigramme, tel que l'affiche Flowgorithm
Exécuter comme dans Flowgorithm, en continu ou forme par forme.
NextDoneMainReal Array debits[4]Integer ii = 0 to Size(debits)debits[i] = 0Output "Débits remis à zéro"End

Une remise à zéro qui va une case trop loin : la borne de fin a perdu son - 1.

Un indice hors du tableau arrête l'exécution

Exécuter ce programme : les quatre premiers tours remplissent debits[0] à debits[3], puis la boucle fait un cinquième tour, où i vaut 4. La case debits[4] n'existe pas : l'exécution s'arrête sur une erreur, avant la sortie. Une erreur d'indice se lit toujours de la même façon : quelle valeur avait l'indice, et jusqu'où vont les cases ?

En Python, le tableau s'appelle une liste, dont les indices commencent aussi à 0. Le parcours s'écrit for i in range(len(temperatures)) : la borne de fin de range est exclue, ce qui absorbe le - 1.

Le texte, caractère par caractère

Un texte se parcourt comme un tableau : Len(s) rend son nombre de caractères, et Char(s, i) rend le caractère d'indice i, en comptant à partir de 0. Le premier caractère est Char(s, 0), le dernier Char(s, Len(s) - 1).

Organigramme, tel que l'affiche Flowgorithm
Exécuter comme dans Flowgorithm, en continu ou forme par forme.
FalseTrueNextDoneFalseTrueMainString code, lettreInteger i, nbInput codeInput lettrenb = 0i = 0 to Len(code) - 1Char(code, i) == lettrenb = nb + 1Output "Le code contient " & nb & " fois " & lettreChar(code, 0) == "P"Output "Autre référence"Output "Référence de pièce détachée"End

Un code produit lu caractère par caractère : compter une lettre, puis vérifier la première.

Pour le code PB-2047-B et la lettre B, le programme affiche Le code contient 2 fois B, puis Référence de pièce détachée. La boucle fait 9 tours, un par caractère, tirets compris. Relancer avec un autre code et une autre lettre, en observant i et nb. Flowgorithm ne propose aucune fonction qui extrait un morceau de texte, par exemple les quatre chiffres d'une référence : tout traitement se construit caractère par caractère, avec Len, Char et une boucle.

Fil rouge : la cuve de traitement

Étape 5. La cuve (rayon 1,5 m, hauteur 4 m) est équipée d'un capteur qui relève le volume d'eau, en litres, à chaque heure pleine, de 0 h à 23 h. Le programme range les 24 relevés dans un tableau, calcule le volume moyen, trouve le pic et l'heure du pic, puis exprime chacun en taux de remplissage. L'indice d'une case est directement l'heure du relevé : volumes[12] est le relevé de midi.

Organigramme, tel que l'affiche Flowgorithm
Exécuter comme dans Flowgorithm, en continu ou forme par forme.
NextDoneFalseTrueNextDoneMainReal Array volumes[24]Integer i, heurePicReal capacite, somme, moyenne, tauxMoyen, tauxPiccapacite = pi * 1.5 ^ 2 * 4 * 1000i = 0 to Size(volumes) - 1Input volumes[i]somme = 0heurePic = 0i = 0 to Size(volumes) - 1somme = somme + volumes[i]volumes[i] > volumes[heurePic]heurePic = imoyenne = somme / Size(volumes)tauxMoyen = moyenne / capacite * 100tauxPic = volumes[heurePic] / capacite * 100Output "Volume moyen : " & ToFixed(moyenne, 1) & " L, soit " & ToFixed(tauxMoyen,1) & " %"Output "Pic : " & ToFixed(volumes[heurePic], 0) & " L à " & heurePic & " h, soit " &ToFixed(tauxPic, 1) & " %"End

Étape 5 du fil rouge. Une première boucle remplit le tableau, une seconde accumule et cherche le pic. Suivre heurePic en pas à pas : il ne change que lorsqu'un relevé dépasse celui qu'il désignait.

Avec les 24 relevés proposés, le programme affiche Volume moyen : 20187.5 L, soit 71.4 % puis Pic : 26100 L à 12 h, soit 92.3 %. À midi, le taux dépasse le seuil haut de 90 %. En pas à pas, observer les cases volumes[0] à volumes[23] se remplir une à une, puis heurePic changer sept fois pendant la seconde boucle.

Une chose se répète : la formule du taux est écrite deux fois, à deux lignes d'écart. Cela fonctionne, mais une correction faite d'un côté et oubliée de l'autre donnerait deux taux incohérents. Le chapitre suivant règle ce défaut.

Exercices type

Organigramme, tel que l'affiche Flowgorithm
NextDoneFalseTrueNextDoneMainReal Array debits[6]Integer i, correctionsi = 0 to Size(debits) - 1Input debits[i]corrections = 0i = 0 to Size(debits) - 1debits[i] < 0debits[i] = 0corrections = corrections + 1Output "Corrections : " & correctionsEnd

Un débitmètre en dérive renvoie parfois des valeurs négatives, physiquement impossibles : le programme les remplace par 0.

L'opérateur saisit 2.4, -0.3, 3.1, -1.2, 0 et 2.8. Que contient le tableau debits à la fin, et qu'affiche le programme ?

La seconde boucle visite les six cases. Seules les cases d'indices 1 et 3 contiennent une valeur strictement négative : elles reçoivent 0, et le compteur augmente deux fois. La case d'indice 4 contient déjà 0, la condition debits[i] < 0 est fausse, et rien ne change. Le tableau contient 2,4 ; 0 ; 3,1 ; 0 ; 0 ; 2,8 et le programme affiche Corrections : 2. Une case se modifie par une affectation dont la cible est debits[i], exactement comme une variable. Et la valeur limite, 0 ici, décide si la comparaison doit être stricte : un débit nul est une mesure valable, qu'il ne faut pas compter comme une correction.

Organigramme, tel que l'affiche Flowgorithm
NextDoneFalseTrueNextDoneMainReal Array mesures[5]Integer i, n, rangMaxInput ni = 0 to n - 1Input mesures[i]rangMax = 0i = 1 to n - 1mesures[i] > mesures[rangMax]rangMax = iOutput "Épaisseur maximale : " & ToFixed(mesures[rangMax], 1) & " mm, mesure " &(rangMax + 1)End

Cinq épaisseurs relevées sur une tôle, dont deux identiques au maximum. Prévoir le rang affiché avant de déplier.

Le contrôleur saisit 5, puis 12.4, 15.1, 15.1, 11.8 et 14.2. Quel rang le programme affiche-t-il, et que faudrait-il changer pour qu'il affiche l'autre ?

La boucle part de l'indice 1, car l'indice 0 sert de point de départ à la comparaison. À l'indice 1, 15.1 > 12.4 est vrai : rangMax passe à 1. À l'indice 2, 15.1 > 15.1 est faux, la comparaison étant stricte : rangMax ne bouge pas. Les deux dernières valeurs sont plus petites. Le programme affiche Épaisseur maximale : 15.1 mm, mesure 2.

Remplacer > par >= fait retenir la dernière case atteignant le maximum, et le programme afficherait la mesure 3. Aucune des deux versions n'est fausse : il faut seulement savoir laquelle on veut, et le choix ne se voit que sur une série où le maximum apparaît deux fois.

Le + 1 dans la sortie convertit un indice en rang : la case d'indice 1 est la deuxième mesure. Afficher rangMax seul annoncerait la mesure 1, ce qui serait faux pour un opérateur qui compte à partir de 1.

Vérification

Vérification rapideon peut se reprendre

1.Un tableau est déclaré avec 10 cases. Quels sont ses indices ?

2.Comment désigner la dernière case d'un tableau t, quelle que soit sa taille ?

3.Le tableau Tab contient 5, 3, 8, 1 et 6, aux indices 0 à 4. Que vaut Tab[Tab[1]] ?

4.Que se passe-t-il si un programme lit t[5] dans un tableau de 5 cases ?

5.Pour chercher le maximum d'un tableau, par quelle valeur commencer ?

6.Une boucle « pour i de 0 à Size(t) - 1 » parcourt un tableau de 6 cases. Combien de tours fait-elle ?

La méthode

  1. Déclarer le tableau avec sa taille, puis écrire toute boucle de parcours de 0 à Size(t) - 1. Ainsi le programme reste juste si la taille change.
  2. Situer chaque instruction par rapport à la boucle : l'initialisation avant, l'accumulation ou le test dedans, l'affichage après.
  3. Accumuler dans une variable mise à 0 avant la boucle ; compter dans une variable augmentée de 1 sous un If.
  4. Chercher un maximum en retenant l'indice de la première case, puis en le remplaçant quand une case le dépasse. Comparer avec > retient le premier maximum, avec >= le dernier.
  5. Convertir un indice en rang avant de l'afficher, si le lecteur compte à partir de 1.
  6. Lire un texte caractère par caractère avec Char(s, i), de 0 à Len(s) - 1 : la règle des indices est la même que pour un tableau.

Synthèse

  • Un tableau range plusieurs valeurs du même type sous un seul nom. Il se déclare avec une taille, et Size(t) rend son nombre de cases.
  • Les indices vont de 0 à Size(t) - 1. La dernière case s'écrit t[Size(t) - 1], et un indice hors de cet intervalle arrête l'exécution au lieu de fausser le résultat.
  • Une case se lit et s'affecte comme une variable ordinaire : t[i] ← 0 est une affectation dont la cible est une case.
  • Un indice est une expression : le plus souvent la variable d'une boucle For, parfois le contenu d'une autre case.
  • Le parcours par une boucle sert à accumuler, compter et chercher. Pour un maximum, retenir l'indice plutôt que la seule valeur, en partant de la première case.
  • Un texte se parcourt de la même façon : Len(s) donne sa longueur, Char(s, i) le caractère d'indice i, à partir de 0.

Mettre en pratique