Tableaux Introduction aux tableaux à une dimension. Déclaration, stockage, initialisation et accès en lecture ou en écriture aux composantes d’un tableau. Affichage d’un tableau. Tableaux à plusieurs dimensions. Regroupement de valeurs de même type.
Les tableaux à une dimension Il s’agit d’une variable structurée formée d’un nombre N de variables simples de même type. Chaque variable simple du tableau est une composante du tableau. Le nombre de composantes N est la dimension du tableau. . . . N composantes On fait souvent le lien avec les mathématiques; on parle alors d’un vecteur de longueur N. Exemple : int Jours[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; Jour est une variable de type tableau de dimension 12 dont les composantes sont de type int. Les 12 composantes sont initialisées par les valeurs respectives 31, 28, …., 31. On peut accéder à chaque composante comme suit : Jours[0], Jours[1], …, Jours[11].
Déclaration d’une variable de type tableau Syntaxe I : Type simple identificateur d’une variable de type tableau [dimension du tableau] Note : L’identificateur d’une variable de type tableau doit respecter les mêmes règles que n’importe quel identificateur de variable. Exemple : int Ensemble_des_notes[45]; int Coordonnees_d_un_point[3]; char Chaine_de_caracteres[80]; float Ensemble_des_pertes_financieres[10]; Note : Plusieurs variables de type tableau dont les composantes sont de même type peuvent être regroupées en utilisant la virgule pour les séparer. Exemple : int Ensemble_des_notes[45], Coordonnees_d_un_point[3]; char c1[4], c2[3]; Note : La dimension du tableau doit être une constante ou une variable constante.
Stockage d’un tableau en mémoire Puisque les composantes d’un tableau sont de même type, celles-ci sont rangées en mémoire de manière consécutive. Le nom d’une variable de type tableau désigne l’adresse de la première composante du tableau. Exemple : short A[5] = { 1200, 2300, 3400, 4500, 5600}; . . . 1200 2300 3400 4500 5600 . . . 1E04 1E06 1E08 1E0A 1E0C 1E0E 1E10 Les adresses des autres composantes sont calculées automatiquement et efficacement relativement à cette adresse de base. Si une composante d’un tableau T a besoin de M (= sizeof(type des composantes)) octets en mémoire, alors l’adresse de la iième composante est T + i * M. Si T est de dimension N alors il occupe N*M octets en mémoire.
Initialisation lors de la déclaration d’un tableau Syntaxe II : Type simple identificateur d’une variable de type tableau [dimension du tableau] = { valeur1 de type simple, valeur2 de type simple, …, valeurn de type simple}; Exemple : int A[5] = { 10, 20, 30, 40, 50 }; float B[4] = { -1.05, 3.33, 87e-5, -12.3E4 }; char voyelle[6] = { 'a', 'e', 'i', 'o', 'u', 'y' }; Note : Le type de ces n valeurs doit correspondre au type des composantes du tableau. Le # de valeurs dans la liste doit correspondre à la dimension du tableau. Si la liste ne contient pas assez de valeurs pour toutes les composantes, les composantes restantes sont initialisées à 0. Ex. : int A[5] = { 10, 20, 30 }; char C[4] = {'a', 'b'}; 10 20 30 'a' 'b' 016 O16 Si le # de valeurs dans la liste est plus grand que la dimension du tableau, il y a erreur de syntaxe.
Accès aux composantes d’un tableau Syntaxe : Nom d’un tableau [expression désignant l’indice d’une composante ] Soit un tableau A à 5 composantes entières, int A[5]; A[0], A[1], A[2], A[3] et A[4] désignent chacune des 5 composantes. Ex. I : Ex. II : int i; for (i = 0; i < 5; i++) { scanf("%d", &A[i]); // ou encore, scanf("%d", A+i); } int somme = 0; for (int i = 0; i < 5; i++) { cin >> A[i]; somme += A[i]; A[i] = A[i] + 2; cout << A[i] << somme; } Note: C ou C++ ne vérifie pas si l’on est ou non en dehors de la portée du tableau. C’est la responsabilité du programmeur de s’en assurer. int A[5] = {0}; for (int i = 0; i < 10; i++) cout << A[i] << " "; // Donne lieu à des situations imprévisibles.
Préséance de l’opérateur []
Exercice I Énoncé : Lire la dimension N d’un tableau de type int (dimension maximale = 50), remplir le tableau à partir de valeurs saisies au clavier, afficher le tableau ainsi que la somme des éléments du tableau. #include <iostream.h> void main() { int N; int tab[50]; int somme = 0; cout << "Entrez la dimension N du tableau : "; cin >> N; for (int i = 0; i < N; i++) cout << "Entrez la " << i << " ieme composante : "; cin >> tab[i]; somme += tab[i]; }
Exercice I (suite) cout << endl << endl <<"Affichage du tableau." << endl; for (int j = 0; j < N; j++) { if((j % 3) == 0) cout << endl; cout << "tab[ " << j << " ] = " << tab[j] << "\t"; } cout << endl << endl << "Somme = " << somme << endl;
Exercice II Énoncé : À partir du tableau précédent, effacer toutes les occurrences de la valeur 0 dans le tableau et tasser les éléments restants. Afficher le tableau réduit. int k = -1; for (j = 0; j < N; j++) if (tab[j] != 0) { k = k + 1; tab[k] = tab[j]; } N = k + 1; // Ne pas faire else N = N -1; cout << endl << endl << "Affichage du tableau reduit." << endl; if((j % 3) == 0) cout << endl; cout << "tab[ " << j << " ] = " << tab[j] << "\t"; À insérer à la fin du programme précédent. Opérationnel même si le tableau réduit n’a aucune compo- sante.
Exercice III Énoncé : Considérer de nouveau le programme de l’exercice #1 et ranger les éléments du tableau dans l’ordre inverse sans utiliser de tableau d’aide. Afficher le tableau inversé. for (int k = 0; k < N / 2; k++) { int echange = tab[k]; tab[k] = tab[N - k - 1]; tab[N - k - 1] = echange; } cout << endl << endl << "Affichage du tableau inverse." << endl; for (j = 0; j < N; j++) if((j % 3) == 0) cout << endl; cout << "tab[ " << j << " ] = " << tab[j] << "\t"; À insérer à la fin du programme de l’exercice #1.
Les tableaux à deux dimensions (2D) Un tableau 2D A est interprété comme un tableau unidimensionnel de dimension L dont chaque composante est un tableau unidimensionnel de dimension C. . . . A . . . . . . . . . L lignes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C colonnes L et C sont les deux dimensions du tableau A renfermant L * C composantes. Note : Le tableau 2D est carré si L est égale à C. Rapprochement avec l’algèbre linéaire : A est une matrice MLxC.
Déclaration des tableaux 2D Syntaxe I : Type simple identificateur d’une variable de type tableau [Nombre_de_lignes] [Nombre_de_colonnes] Exemple : int Note[10][20]; Mémorise les 10 notes de 20 élèves. Chaque ligne représente les notes de tous les élèves dans un devoir. Chaque colonne représente toutes les notes d’un élève. Exemple : enum Jours_de_la_semaine { Dimanche = 0, Lundi, Mardi, Mercredi, Jeudi, Vendredi, Samedi}; float Production[7][52]; . . . Production[Lundi][24] = 39.4f;
Initialisation des tableaux 2D Syntaxe II : Type simple identificateur d’une variable de type tableau [Nombre_de_lignes] [Nombre_de_colonnes] = { { valeur11 de type simple, valeur12 de type simple, …, valeur1C de type simple}, { valeur21 de type simple, valeur22 de type simple, …, valeur2C de type simple}, . . . { valeurL1 de type simple, valeurL2 de type simple, …, valeurLC de type simple} }; La liste des valeurs respectives est placée entre accolades. À l’intérieur de la liste, les composantes de chaque ligne sont encore une fois comprises entre accolades. Exemple : char Texte[4][2] = { { 'A', 'B'}, { 'C', 'D'}, { 'E', 'F'}, { 'G', 'H'} }; Note : Il n’est pas nécessaire d’indiquer toutes les valeurs. Les valeurs manquantes seront initialisées à zéro. int tab[3][2] = { {123, 456}, {789 }}; // 123 456 789 0 0 0 Il est défendu d’indiquer trop de valeurs.
Mémorisation d’un tableau 2D Comme pour les tableaux unidimensionnels, le nom du tableau représente l’adresse du premier élément du tableau en position (0, 0). Les composantes d’un tableau 2D sont stockés ligne par ligne en mémoire. Exemple : short A[3][2] = { {1, 2}, {10, 20}, {100, 200} }; . . . 1 2 10 20 100 200 . . . 1E04 1E06 1E08 1E0A 1E0C 1E0E 1E10 1E12 A Si chaque composante nécessite M octets, la matrice occupe L * C * M octets consécutifs en mémoire. Calcul de l’adresse de la composante en position (i, j), 0 i < L, 0 j < C : A + (C * i + j) * M.
Accès aux composantes d’un tableau 2D Syntaxe : Nom d’un tableau [Indice de ligne] [Indice de colonne] 0 à L - 1 0 à C - 1 La composante de la Mième ligne et de la Nième colonne : A[M-1][N-1] Les éléments d’un tableau de dimension L x C se présentent comme suit : A[0][0] A[0][1] A[0][2] . . . A[0][C-1] A[1][0] A[1][1] A[1][2] . . . A[1][C-1] A[2][0] A[2][1] A[2][2] . . . A[2][C-1] . . . . . . . . . . . . . . . A[L-1][0] A[L-1][1] A[L-1][2] . . . A[L-1][C-1]
Construction et affichage d’un tableau 2D #include <iostream.h> void main() { const L = 5; // Nombre de lignes de la matrice. const C = 3; // Nombre de colonnes de la matrice. int A[L][C] = {{0}}; cout << "Affichage d'une matrice nulle." << endl << endl; for (int i = 0; i < L; i++) for (int j = 0; j < C; j++) cout << "A(" << i << ", " << j << ") = " << A[i][j] << "\t"; cout << endl; } Bonne pratique de programmation : éviter les nombres magiques.
Construction et affichage d’un tableau 2D cout << endl << endl << "Saisie au clavier des donnees d'une matrice." << endl << endl; for (i = 0; i < L; i++) for (int j = 0; j < C; j++) { cout << "\nA(" << i << ", " << j << ") = "; cin >> A[i][j]; // scanf("%d", &A[i][j]); } cout << "\nAffichage d'une matrice." << endl << endl; cout << "A(" << i << ", " << j << ") = " << A[i][j] << "\t"; cout << endl;
Somme des lignes et des colonnes d’un tableau 2D Restriction : Utiliser une seule variable pour la somme des lignes et des colonnes. #include <iostream.h> void main() { const L = 5; // Nombre de lignes de la matrice. const C = 3; // Nombre de colonnes de la matrice. int A[L][C]; cout << "Saisie au clavier des donnees d'une matrice." << endl << endl; for (int i = 0; i < L; i++) for (int j = 0; j < C; j++) cout << "\nA(" << i << ", " << j << ") = "; cin >> A[i][j]; }
Somme des lignes et des colonnes d’un tableau 2D Restriction : Utiliser une seule variable pour la somme des lignes et des colonnes. cout << "\nAffichage d'une matrice." << endl << endl; for (i = 0; i < L; i++) { int somme = 0; for (int j = 0; j < C; j++) somme += A[i][j]; cout << A[i][j] << "\t\t"; } cout << "A(" << i << ", .) = " << somme << endl; for (int i = 0; i < L; i++) somme += A[i][j]; cout << "A(., " << j << ") = " << somme << "\t"; cout << endl;
Insérer une valeur dans un tableau trié en ordre croissant #include <iostream.h> void main() { const E = 5; // Nombre d'éléments du tableau. int A[E + 1]; int valeur; // Saisie des données. cout << "Saisie au clavier des donnees du tableau." << endl << endl; for (int i = 0; i < E; i++) cout << "\nA(" << i << ") = "; cin >> A[i]; } cout << "Insertion d'une nouvelle valeur a inserer : "; cin >> valeur;
Insérer une valeur dans un tableau trié en ordre croissant // Insertion d'une nouvelle valeur. if (valeur > A[E - 1]) A[E] = valeur; // Ajout de la nouvelle valeur à la fin. else { // Recherche de la position d'insertion dans A. int u = 0, v = E-1; while (u < v) // A[u-1] < valeur <= A[v]. // Par convention, on suppose que A[-1] est égale à -. int w = (u + v) / 2; if(valeur <= A[w]) v = w; else u = w+1; } // À la sortie de la boucle, u est égale à v (u > v est impossible). // Si la nouvelle valeur à insérer existait déjà, // alors A[u] est égale à valeur // sinon A[u] est le plus petit élément plus grand que valeur.
Insérer une valeur dans un tableau trié en ordre croissant // Il s'agit maintenant de déplacer d'une position vers la droite // les éléments de A en position u, u + 1, u + 2, ..., E. for (int k = E + 1; k > u; k--) A[k] = A[k-1]; // Finalement, il s'agit de placer la nouvelle valeur en position u. A[u] = valeur; } // Affichage d'un tableau. cout << "\nAffichage d'un tableau." << endl << endl; for (i = 0; i < E+1; i++) { if((i % 3) == 0) cout << endl; cout << A[i] << "\t"; cout << endl;
Statistique des notes Écrire un programme qui lit la note sur 60 de chaque élève d’une classe à un examen. Ces notes sont rangées dans un tableau de dimension N où N est le nombre d’élèves de la classe. Rechercher et afficher les notes minimale et maximale, la moyenne des notes. Construire un histogramme comme dans l’exemple suivant.
Statistique des notes #include <iostream.h> void main() { const N = 15; // Nombre d'élèves. int Notes[N]; // Saisie des données. cout << "Saisie des notes :" << endl << endl; for (int i = 0; i < N; i++) cout << i << ". "; cin >> Notes[i]; }
Statistique des notes // Calcul des statistiques. int minimum = Notes[0], maximum = Notes[0], total = Notes[0]; int Histo[7] = {0}; for (i = 1; i < N; i++) { if (minimum > Notes[i]) minimum = Notes[i]; if (maximum < Notes[i]) maximum = Notes[i]; total += Notes[i]; Histo[6] += (Notes[i] == 60); Histo[5] += (Notes[i] >= 50 && Notes[i] < 60); Histo[4] += (Notes[i] >= 40 && Notes[i] < 50); Histo[3] += (Notes[i] >= 30 && Notes[i] < 40); Histo[2] += (Notes[i] >= 20 && Notes[i] < 30); Histo[1] += (Notes[i] >= 10 && Notes[i] < 20); Histo[0] += (Notes[i] < 10); }
Statistique des notes // Affichage des résultats. cout << "La note minimale est : " << minimum << endl; cout << "La note maximale est : " << maximum << endl; cout << "La moyenne des notes est : " << total / N << endl << endl; int Hauteur = Histo[0]; for (i = 1; i < 7; i++) if (Hauteur < Histo[i]) Hauteur = Histo[i]; for (int j = Hauteur; j > 0; j--) { cout << j << "> "; for (i = 0; i < 7; i++) if (Histo[i] >= j) cout << "####### "; else cout << "\t"; cout << endl; } cout << "+-------+-------+-------+-------+-------+-------+-------+\n" << "I 0 - 9 I 10-19 I 20-29 I 30-39 I 40-49 I 50-59 I 60 I\n\n";
Multiplication de 2 matrices Au x v et Bv x w #include <iostream.h> void main() { const u = 5, v = 3, w = 10; // Dimension des 2 matrices. int A[u][v], B[v][w], C[u][w] = {{0}}; cout << "Saisie au clavier des donnees de A." << endl << endl; for (int i = 0; i < u; i++) for (int j = 0; j < v; j++) cout << "\nA(" << i << ", " << j << ") = "; cin >> A[i][j]; } cout << "Saisie au clavier des donnees de B." << endl << endl; for (i = 0; i < v; i++) for (int j = 0; j < w; j++) cout << "\nB(" << i << ", " << j << ") = "; cin >> B[i][j];
Multiplication de 2 matrices Au x v et Bv x w // Calcul du produit C = A x B. for (i = 0; i < u; i++) for (int j = 0; j < w; j++) for (int k = 0; k < v; k++) C[i][j] += A[i][k] * B[k][j]; // Affichage des 3 matrices. cout << endl << endl << "Matrice A" << endl << endl; { for (int j = 0; j < v; j++) cout << A[i][j] << "\t"; cout << endl; }
Multiplication de 2 matrices Au x v et Bv x w cout << endl << endl << "Matrice B" << endl << endl; for (i = 0; i < v; i++) { for (int j = 0; j < w; j++) cout << B[i][j] << "\t"; cout << endl; } cout << endl << endl << "Matrice C" << endl << endl; for (i = 0; i < u; i++) for (int j = 0; j < w; j++) cout << C[i][j] << "\t"; Note : On peut construire des tableaux de dimension quelconque. Ex. : int table[10][5][25];
Recherche de points-cols Rechercher dans une matrice A les éléments qui sont à la fois un maximum sur leur ligne et un minimum sur leur colonne. Afficher les positions et les valeurs de tous les points-cols trouvés. Stratégie : Construire 2 matrices booléennes Max et Min de même dimension que A définies comme suit : Max[i][j] = true si A[i][j] est un maximum sur la ligne i, false autrement. Min[i][j] = true si A[i][j] est un minimum sur la colonne j, false autrement. Exemple : 5 6 7 7 2 2 8 9 6 3 2 9 7 A =
Recherche de points-cols #include <iostream.h> void main() { const m = 3, n = 5; // Dimension de la matrice A. int A[m][n]; // Saisie des données. cout << "Saisie au clavier des donnees de la matrice A." << endl << endl; for (int i = 0; i < m; i++) for (int j = 0; j < n; j++) cout << "\nA(" << i << ", " << j << ") = "; cin >> A[i][j]; } cout << endl << endl;
Recherche de points-cols // Affichage de la matrice A. for (i = 0; i < m; i++) { for (int j = 0; j < n; j++) cout << A[i][j] << "\t"; } cout << endl; cout << endl << endl; // Construction des matrices booléennes. bool max[m][n] = {{false}}; bool min[m][n] = {{false}};
Recherche de points-cols for (i = 0; i < m; i++) { int maximum = A[i][0]; for (int j = 1; j < n; j++) if (maximum < A[i][j]) maximum = A[i][j]; for (j = 0; j < n; j++) if (A[i][j] == maximum) max[i][j] = true; } for (int j = 0; j < n; j++) int minimum = A[0][j]; for (int i = 1; i < m; i++) if (minimum > A[i][j]) minimum = A[i][j]; if (A[i][j] == minimum) min[i][j] = true; for (j = 0; j < n; j++) if (min[i][j] && max[i][j]) cout << "(" << i << ", " << j << ")\t" << A[i][j] << endl;
Construction d’un agenda et affichage des disponibilités #include <iostream.h> #include <iomanip.h> void main() { enum Jour {Dimanche, Lundi, Mardi, Mercredi, Jeudi, Vendredi, Samedi}; enum Periode {P9h00, P9h20, P9h40, P10h00, P10h20, P10h40, P11h00, P11h20, P11h40, P13h00, P13h20, P13h40, P14h00, P14h20, P14h40, P15h00, P15h20, P15h40, P16h00, P16h20, P16h40}; bool Agenda[Samedi + 1][P16h40+1] = {{false}}; char chaine[Samedi + 1][8] = {{'d', 'i', 'm', 'a', 'n', 'c', 'h', 'e'}, {'l', 'u', 'n', 'd', 'i'}, {'m', 'a', 'r', 'd', 'i'}, {'m', 'e', 'r', 'c', 'r', 'e', 'd', 'i'}, {'j', 'e', 'u', 'd', 'i'}, {'v', 'e', 'n', 'd', 'r', 'e', 'd', 'i'}, {'s', 'a', 'm', 'e', 'd', 'i'}}; // En C seulement, on peut écrire : // char chaine[Samedi + 1][8] = // {"dimanche", "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi"};
Construction d’un agenda et affichage des disponibilités // Dans cet agenda, chaque période est de 20 minutes et les seules périodes // disponibles dans une journée sont de 9h. à 12h00 et de 13h00 à 17h00. // Au départ, on suppose qu'aucun rendez-vous n'a encore été pris. Agenda[Mardi][4] = true; // ............... Les prises de rendez-vous sont terminées. // On affiche maintenant les disponibilités dans la semaine. for (int jour = Dimanche; jour <= Samedi; jour++) { cout << "Les periodes suivantes pour le "; for (int i = 0; i < 8; i++) cout << chaine[jour][i]; cout << " sont disponibles : "; for (int periode = P9h00; periode <= P16h40; periode++) if (! Agenda[jour][periode]) int p = 0; if (periode >= 9) p = 1; p += periode/3; cout << "\t" << p + 9 << "h" << setw(2) << setfill('0') << 20*(periode%3); } cout << endl << endl;
Agence de rencontres – énoncé du problème Une maison bien connue utilise l’informatique dans la recherche de l’âme-sœur ou de l’âme-frère. N candidats et N candidates répondent à un questionnaire portant sur leurs intérêts dans divers domaines tels que la musique, le sport, le cinéma, etc. Ils expriment leur préférence en choisissant parmi les degrés suivants, le chiffre correspondant à leur sentiment : N’aime pas du tout N’aime pas N’aime pas beaucoup Indifférent Aime un peu Aime bien Aime beaucoup. Le problème consiste à déterminer le couple le mieux assorti en calculant la somme des carrés des différences obtenues aux questions posées aux participants pour chaque couple potentiel.
Agence de rencontres #include <iostream.h> void main() { const int N = 5; // Nombre de participants. const int M = 4; // Nombre de questions. char prenom_masculin[N][10]; // Prénom des N participants. char prenom_feminin[N][10]; // Prénom des N participantes. int reponse_masculin[N][M]; // Réponse des hommes. int reponse_feminin[N][M]; // Réponse des femmes. int differences[N][N]; // Différences entre chaque couple // Saisie des prénoms masculins et féminins. for (int i = 0; i < N; i++) cout << "Participant # " << i+1 << " : "; cin >> prenom_masculin[i]; } for (i = 0; i < N; i++) cout << "Participante # " << i+1 << " : "; cin >> prenom_feminin[i];
Agence de rencontres // Saisie des réponses aux questions chez les hommes et les femmes. for (i = 0; i < N; i++) { cout << "Participant # " << i+1 << " : " << endl; for (int j = 0; j < M; j++) cout << "\tQuestion # " << j+1 << " : (1 - 7)"; cin >> reponse_masculin[i][j]; } cout << endl; cout << "Participante # " << i+1 << " : " << endl; cin >> reponse_feminin[i][j];
Agence de rencontres // Différences entre chaque couple. for (i = 0; i < N; i++) for (int j = 0; j < N; j++) { int somme = 0; for (int k = 0; k < M; k++) somme += (reponse_masculin[i][k] - reponse_feminin[j][k]) * (reponse_masculin[i][k] - reponse_feminin[j][k]); differences[i][j] = somme; }
Agence de rencontres // Couple le mieux assorti. int G = 0, F = 0, Difference = differences[0][0]; for (i = 0; i < N; i++) for (int j = 0; j < N; j++) if (Difference < differences[i][j]) { Difference = differences[i][j]; G = i; F = j; } // Affichage des prénoms du couple le mieux assorti. cout << "Le couple le mieux assorti est : " << prenom_masculin[G] << " et " << prenom_feminin[F] << "." << endl << endl; Note : Comment feriez-vous pour former les N couples ? Est-ce optimal ?