8. Les tableaux P. Costamagna – ISEN N1
A. Utilité Exemple Imaginons un programme, pour lequel nous avons besoin simultanément de 12 valeurs (par exemple, des notes pour calculer une moyenne). La seule solution dont nous disposons à l’heure actuelle consiste à déclarer douze variables, appelées par exemple Notea, Noteb, Notec … ou N1, N2, N3, etc. Au moment du calcul, on aura obligatoirement une formule du genre : Moy = (N1 + N2 + N3 + N4 + N5 + N6 + N7 + N8 + N9 + N10 + N11 + N12 ) / 12 Ce qui est assez laborieux …. Le problème augmente avec le nombre de données à gérer. Pb supplémentaire : cas où l’on ne connaît pas par avance le nombre de valeurs à traiter. P. Costamagna
A. Utilité (suite) L’utilisation de variables simples montre ici ses limites : la déclaration de ces variables devient très vite fastidieuse on ne dispose d’aucun élément du langage pour traiter globalement ces variables si le nombre de notes vient à varier, l’écriture du code devient ingérable. C’est pourquoi les langages de programmation nous permettent de représenter des collections de données de même type sous forme de tableaux: En fixant un nom commun à l’ensemble des variables En repérant chaque valeur par un indice. P. Costamagna
B. Définition Tableau = variable indicée composée de plusieurs données de même nature. Stockage contiguë en mémoire. L’espace mémoire occupé est conditionné par le type de donnée que le tableau contient. Un tableau est déterminé par : un nom unique un type unique applicable à l’ensemble des éléments du tableau. Comme toute variable, un tableau doit être déclaré et initialisé avant d’être utilisé. P. Costamagna
D. Déclaration Permet de réserver en mémoire l’espace nécessaire pour ranger tous les éléments du tableau. Il faut donc indiquer: Le nombre d’éléments maximum pouvant être stocké dans le tableau La nature des éléments contenus dans le tableau Syntaxe Nombre de valeurs maximum pouvant être contenues dans le tableau int float char bool id_tableau [ ] valeur ; Identificateur choisi pour représenter le tableau Les crochets sont obligatoires Type à déterminer en fonction de la nature des valeurs contenues dans le tableau P. Costamagna
D. Déclaration (suite) Exemples int T [ 10 ]; permet de réserver en mémoire l’espace nécessaire pour pouvoir stocker dans la variable T 10 entiers float Note [ 15 ]; permet de réserver en mémoire l’espace nécessaire pour pouvoir stocker dans la variable Note 15 réels Remarques La taille d’un tableau doit être connue lors de la compilation tous les emplacements ne seront pas obligatoirement occupés. les tableaux consomment beaucoup de place en mémoire. impossible d’utiliser une variable pour déclarer la taille d’un tableau: int n; int tab[ n ] ; provoquera une erreur P. Costamagna
E. Accès aux éléments d’un tableau Le nom donné au tableau ne suffit pas On utilise un nombre appelé indice qui, combiné avec le nom du tableau, permet de décrire exactement chaque élément. Chaque élément du tableau peut ainsi être manipulé comme une variable. Syntaxe Valeur correspondant à la case du tableau voulue id_tableau [ ] indice Identificateur choisi pour représenter le tableau Les crochets sont obligatoires P. Costamagna
E. Accès aux éléments d’un tableau Remarques Soit un tableau déclaré int T[5] L'indice du premier élément d’un tableau est 0 (en langage C) , donc le dernier sera n-1. ( T[0] à T[4]) L’accès à un élément d’un tableau hors réservation ne provoquera pas d’erreur de compilation, mais des surprises à l’exécution. ( ex T[9]) Un indice est toujours un entier positif . ( ex T[-3] ou T[2.34]) L’indice peut être exprimé directement comme un nombre en clair, mais il peut être aussi une variable, ou une expression calculée. ( ex T[4] ou T[2 + i], i étant déterminé) ; P. Costamagna
F. Manipuler les éléments d’un tableau Un élément d’un tableau (repéré par le nom du tableau et son indice) pouvant être manipulé exactement comme une variable, on peut donc effectuer des opérations sur des éléments de tableau Exemple Soit un tableau de 10 entiers : int Toto[10]; Pour affecter la valeur 6 au 8ème élément on écrira : Toto [ 7 ] = 6; Pour affecter au 10ème élément le résultat de l'addition des éléments 1 et 2, on écrira : Toto [ 9 ] = Toto [ 0 ] + Toto [ 1 ]; P. Costamagna
G. Initialiser un tableau Au moment de la déclaration d’un tableau, les valeurs des éléments qu'il contient ne sont pas définies, il faut donc les initialiser. 1ère méthode 2ème méthode En affectant des valeurs aux éléments un par un : T[0] = 0 ; T[1] = 0 ; T[2] = 0 ;… En incrémentant un indice à l’aide d'une boucle : int T[10]; int cpt; for (cpt = 0; cpt <= 9; cpt= cpt+1) T[cpt] = 0; Méthode laborieuse et peu efficace. A utiliser si les éléments du tableau doivent être initialisés à une valeur unique ou une valeur logique (proportionnelle à l'indice par exemple). P. Costamagna
G. Initialiser un tableau (suite1) 3ème méthode Utile pour initialiser un tableau avec des valeurs spécifiques, au moment de sa déclaration en plaçant entre accolades les valeurs, séparées par des virgules : int T[10] = {1, 2, 6, 5, 2, 1, 9, 8, 1, 5}; Remarques: - Le nombre de valeurs entre accolades ne doit pas être supérieur au nombre d'éléments du tableau - Les valeurs entre accolades doivent être des constantes (l'utilisation de variables provoquera une erreur du compilateur) - Si le nombre de valeurs entre accolades est inférieur au nombre d'éléments du tableau, les derniers éléments sont initialisés à 0 - Il doit y avoir au moins une valeur entre accolades, l'instruction suivante permet d'initialiser tous les éléments du tableau à zéro : int T[10] = {0}; P. Costamagna
G. Initialiser un tableau (suite2) Il est conseillé d'employer des constantes dans vos programmes notamment pour déterminer la taille des tableaux. Exemple #define NB_ELEMENT_T 10 int Toto[NB_ELEMENT_T]; int Indice; for (Indice = 0; Indice < NB_ELEMENT_T; Indice= Indice+1) T[Indice] = 0; Avantages: - Moins d'erreurs d'exécution dues à un débordement difficile à déceler. - Modification de la taille du tableau facile à traiter : il suffit de changer le define en début du code source. - Meilleure lisibilité du code. ² - P. Costamagna
H. Utilisation d’un tableau L’utilisation globale d’un tableau est impossible. int t1[20]; int t2[10]; Il n’est pas possible d’écrire t1 = t2 Exercice Ecrire un programme qui effectue la saisie des éléments d’un tableau pouvant contenir au maximum 10 entiers, puis recherche et affiche sa valeur maximum et son rang. P. Costamagna
I. Correction /* Saisie des éléments du tableau */ for (i=0; i<=nb-1; i=i+1) { ecrisChaine ("Entrer la valeur "); ecrisEntier (i); ecrisChaine (" du tableau "); V [ i ] = lisEntier(); } /* Recherche du max et de son rang */ max = V [ 0 ]; /* initialisation avec le 1er élt */ rmax = 0; for (i=1; i<=nb-1; i=i+1) if (V [ i ] > max) max = V [ i ]; /* on récupère le rmax = i; nouveau max */ /* Affichage du résultat */ sautDeLigne(); ecrisChaine ("Le maximum du tableau est "); ecrisEntier (max); ecrisChaine (" au rang "); ecrisEntier (rmax+1); system ("pause"); return 0; I. Correction #include "ESLib.h" #define dim 10 /* taille du tableau */ int main () { int nb; /* nombre d'élèments effectifs du tableau */ int i; /* compteur */ int V [ dim ]; /* tableau de données */ int max, rmax; /* valeur et rang du maximum */ /* Vérification de la taille du tableau */ do ecrisChaine ("Donner la taille du tableau "); nb = lisEntier(); } while ((nb<=0) || (nb >dim)); P. Costamagna
J. Tableaux et sous-programmes Un tableau peut être utilisé comme paramètre d’un sous-programme. Un tableau ne peut pas être renvoyé par l’instruction return d’une fonction. Le passage par valeur d’un tableau en C n’existe pas. Le mode de transmission est automatiquement effectué par adresse. § Soit f une fonction et t un tableau pouvant contenir au maximum 10 entiers Déclaration void f (int * t) void f (int t [10]) Appel f (&t[0]); f ( t ); P. Costamagna
K. Exercice Ecrire deux fonctions qui affichent le contenu d’un tableau en utilisant les 2 techniques de transmission d’arguments décrites précédemment et le programme principal qui lance ces 2 fonctions. Correction /* 2ème méthode */ void Affiche2Tableau (int *A) { int i; /* compteur */ for (i =0; i<= dim-1; i = i+1) ecrisEntier (A[i]); ecrisChaine (" - "); } #include "ESLib.h" #define dim 5 /* taille du tableau */ /* 1ère méthode */ void Affiche1Tableau (int A[dim]) { int i; /* compteur */ for (i =0; i<= dim-1; i = i+1) ecrisEntier (A[i]); ecrisChaine (" - "); } P. Costamagna
L. Correction /* Programme principal */ int main () { int U[ dim ]={ 1,2,3,4,5 }; /* tableau de données */ int V[ dim ]={ 6,7,8 }; Affiche1Tableau (U); sautDeLigne(); Affiche2Tableau (&V[0]); Affiche1Tableau (&U[0]); Affiche2Tableau (V); system ("pause"); return 0; } P. Costamagna
typedef int tabcent [100] ; M. Notion de type Possible de définir des synonymes de types = alias et non pas nouveau type de donnée. Si la déclaration int tabcent [100] ; définit une variable de type « tableau de 100 entiers » appelé tabcent La ligne typedef int tabcent [100] ; ne définit aucune variable, mais fait du mot tabcent un alias du type « tableau de 100 entiers » Il devient possible d’écrire: tabcent A ; qui définit la variable A de type « tableau de 100 entiers ». P. Costamagna
N. Tableaux à 2 dimensions Un tableau à 1 dimension, correspond à une liste ordonnée de valeurs. Un tableau à 2 dimensions est un tableau de tableau. Il s’agit d’un tableau dont chaque élément est lui-même un tableau. 1 2 3 4 5 6 7 8 9 10 11 12 est stocké en mémoire sous la forme: Lignes 1 2 3 4 5 6 7 8 9 10 11 12 Colonnes P. Costamagna
O. Déclaration d’un tableau à 2 dimensions Le nom donné au tableau ne suffit pas Pour accéder à un élément d’un tel tableau, il faut utiliser 2 indices : - le premier relatif à la ligne - le second relatif à la colonne Syntaxe Nombre de lignes maximum pouvant être contenues dans le tableau Nombre de colonnes maximum pouvant être contenues dans le tableau int float char bool nb ligne nb colonne id_tableau [ ] [ ] ; Type à déterminer en fonction de la nature des valeurs contenues dans le tableau Identificateur choisi pour représenter le tableau Les doubles paires de crochets sont obligatoires P. Costamagna
P. Accès aux éléments d’un tableau 2D Pour accéder à un élément du tableau, il suffit de donner le nom du tableau, suivi de 2 indices, le premier correspondant à la ligne, le 2ème correspondant à la colonne. Syntaxe Valeur correspondant à l’indice de ligne Valeur correspondant à l’indice de colonne id_tableau [ ] Indice ligne [ ] Indice colonne Identificateur choisi pour représenter le tableau Les crochets sont obligatoires P. Costamagna
P. Accès aux éléments d’un tableau 2D (suite) Soit T le tableau suivant: Correspond à l’élément T [1] [2] Colonnes 1 2 3 Lignes 1 2 3 4 5 6 7 8 9 10 11 12 1 2 P. Costamagna
Q. Initialiser un tableau 2D Au moment de la déclaration d’un tableau, les valeurs des éléments qu'il contient ne sont pas définies, il faut donc les initialiser. 1ère méthode 2ème méthode En affectant des valeurs aux éléments un par un : T[0] [0] = 0 ; T[0] [1] = 0 ; … En utilisant 2 boucles imbriquées pour dérouler chaque indice : int T[3] [5]; int i, j; /* remplissage ligne à ligne */ for (i = 0; i < 3; i= i+1) for (j = 0; j < 5; j = j+1) T[i] [j] = 2; Méthode laborieuse et peu efficace. P. Costamagna
Q. Initialiser un tableau 2D (suite) 3ème méthode Utile pour initialiser un tableau avec des valeurs spécifiques, au moment de sa déclaration en plaçant entre accolades les valeurs, séparées par des virgules : int T[3] [5] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; Cette technique exploite la manière dont les éléments d’un tableau sont rangés en mémoire. int T[3] [5] = { {1, 2, 3, 4, 5}, { 6, 7, 8, 9, 10}, { 11, 12, 13, 14, 15} }; Cette 2ème technique revient à considérer notre tableau comme formé de 3 tableaux de 5 éléments chacun. P. Costamagna
R. Exercice Ecrire un sous-programme remplissant une matrice unité carrée. Le nombre de lignes / colonnes sera saisi dans le PP. L’affichage sera réalisé par le PP. Une telle matrice est caractérisée par les éléments de la diagonale à 1 et les autres à 0 Correction #include "ESLib.h" void unite (int MAT [ 9 ] [ 9 ], int N) { int i, j; /* compteurs */ for (i = 0; i < N; i = i+1) for (j = 0; j < N; j = j + 1) if ( i == j) /* diagonale */ MAT[ i ] [ j ] = 1; else /* ailleurs */ MAT[ i ] [ j ] = 0; } P. Costamagna
S. Correction /* Programme principal */ int main () { int dim; /* taille de la matrice unité */ int U [9][9]; int i, j; /* compteurs */ /* Vérification de la taille du tableau */ do ecrisChaine (« Dimension de la matrice "); dim = lisEntier(); } while ((dim <= 0) || (dim > 9)); /* Remplissage de la matrice */ unite (U, dim); /* Affichage de la matrice unité */ for (i = 0; i< dim; i = i+1) { for (j = 0; j < dim; j = j + 1) ecrisEntier (U [ i ] [ j ]); tabulation(); } sautDeLigne(); system ("pause"); return 0; P. Costamagna
T. Tableaux à plus de 2 dimensions Le principe est le même que pour un tableau à 2 dimensions. Il suffit d’ajouter les indices nécessaires. Le nombre de dimension n'est pas limité Exemple Dimension 3 Il s’agit d’un tableau TAB [ i ] [ j ] [ k ] i = nb lignes k = nb tab 2D j = nb colonnes P. Costamagna