• 50 heures
  • Difficile

Ce cours est visible gratuitement en ligne.

Ce cours existe en livre papier.

course.header.alt.is_certifying

Vous pouvez être accompagné et mentoré par un professeur particulier par visioconférence sur ce cours.

J'ai tout compris !

Mis à jour le 02/08/2019

Manipulez les tableaux

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Dans de très nombreux programmes, on a besoin d'avoir plusieurs variables du même type et qui jouent quasiment le même rôle. Pensez par exemple à la liste des utilisateurs d'un site web : cela représente une grande quantité de variables de type string. Ou les dix meilleurs scores de votre jeu, que vous stockerez dans différentes cases mémoires, toutes de type int.
Le C++, comme presque tous les langages de programmation, propose un moyen simple de regrouper des données identiques dans un seul paquet. Et comme l'indique le titre du chapitre, on appelle ces regroupements de variables des tableaux.

Dans ce chapitre, je vais vous apprendre à manipuler deux sortes de tableaux. Ceux dont la taille est connue à l'avance, comme pour la liste des dix meilleurs scores, et ceux dont la taille peut varier en permanence, comme la liste des visiteurs d'un site web qui, généralement, ne cesse de grandir.
Vous vous en doutez certainement, les tableaux dont la taille est fixée à l'avance sont plus faciles à utiliser et c'est donc par eux que nous allons commencer.

Les tableaux statiques

Je vous ai parlé dans l'introduction de l'intérêt des tableaux pour le stockage de plusieurs variables de même type. Voyons cela avec un exemple bien connu, la liste des meilleurs scores du jeu révolutionnaire que vous allez créer un jour.

Un exemple d'utilisation

Si vous voulez afficher la liste des 5 meilleurs scores des joueurs, il va vous falloir en réalité deux listes : la liste des noms de joueurs et la liste des scores qu'ils ont obtenus. Nous allons donc devoir déclarer 10 variables pour mettre toutes ces informations dans la mémoire de l'ordinateur. On aura par exemple :

string nomMeilleurJoueur1("Nanoc");
string nomMeilleurJoueur2("M@teo21");
string nomMeilleurJoueur3("Albert Einstein");
string nomMeilleurJoueur4("Isaac Newton");
string nomMeilleurJoueur5("Archimede");

int meilleurScore1(118218);
int meilleurScore2(100432);
int meilleurScore3(87347);
int meilleurScore4(64523);
int meilleurScore5(31415);

Et pour afficher tout cela, il va aussi falloir pas mal de travail.

cout << "1) " << nomMeilleurJoueur1 << " " << meilleurScore1 << endl;
cout << "2) " << nomMeilleurJoueur2 << " " << meilleurScore2 << endl;
cout << "3) " << nomMeilleurJoueur3 << " " << meilleurScore3 << endl;
cout << "4) " << nomMeilleurJoueur4 << " " << meilleurScore4 << endl;
cout << "5) " << nomMeilleurJoueur5 << " " << meilleurScore5 << endl;

Cela fait énormément de lignes ! Imaginez maintenant que vous vouliez afficher les 100 meilleurs scores et pas seulement les 5 meilleurs. Ce serait terrible, il faudrait déclarer 200 variables et écrire 100 lignes quasiment identiques pour l'affichage ! Autant arrêter tout de suite, c'est beaucoup trop de travail.

C'est là qu'interviennent les tableaux : nous allons pouvoir déclarer les 100 meilleurs scores et les noms des 100 meilleurs joueurs d'un seul coup. On va créer une seule case dans la mémoire qui aura de la place pour contenir les 100intqu'il nous faut et une deuxième pour contenir les 100string. Magique non ?

Dans cet exemple, nous avons besoin de 100 variables, c'est-à-dire 100 places dans le tableau. C'est ce qu'on appelle, en termes techniques, la taille du tableau. Si la taille du tableau reste inchangée et est fixée dans le code source, alors on parle d'un tableau statique. Parfait ! C'est ce dont nous avons besoin pour notre liste des 100 meilleurs scores.

Déclarez un tableau statique

Comme toujours en C++, une variable est composée d'un nom et d'un type. Comme les tableaux sont des variables, cette règle reste valable. Il faut juste ajouter une propriété supplémentaire, la taille du tableau. Autrement dit, le nombre de compartiments que notre case mémoire va pouvoir contenir.

La déclaration d'un tableau est très similaire à celle d'une variable :

Déclaration d'un tableau statique

On indique le type, puis le nom choisi et enfin, entre crochets, la taille du tableau. Voyons cela avec un exemple :

#include <iostream>
using namespace std;

int main()
{
   int meilleurScore[5];       //Déclare un tableau de 5 int 

   double anglesTriangle[3];   //Déclare un tableau de 3 double

   return 0;
}

Voyons à quoi ressemble la mémoire avec un de nos schémas habituels :

La mémoire de l'ordinateur après avoir déclaré deux tableaux
La mémoire de l'ordinateur après avoir déclaré deux tableaux

On retrouve les deux zones mémoires avec leurs étiquettes mais, cette fois, chaque zone est découpée en cases : trois cases pour le tableau anglesTriangleet cinq cases pour le tableau meilleurScore. Pour l'instant, aucune de ces cases n'est initialisée. Leur contenu est donc quelconque.

Il est également possible de déclarer un tableau en utilisant comme taille une constante de type intouunsigned int. On indique simplement le nom de la constante entre les crochets, à la place du nombre.

int const tailleTableau(20);   //La taille du tableau
double anglesIcosagone[tailleTableau];

Je vous conseille de toujours utiliser des constantes pour exprimer les tailles de vos tableaux plutôt que d'indiquer directement la taille entre les crochets. C'est une bonne habitude à prendre.

Bon. Nous avons de la place dans la mémoire. Il ne nous reste plus qu'à l'utiliser.

Accédez aux éléments d'un tableau

Chaque case d'un tableau peut être utilisée comme n'importe quelle autre variable, il n'y a aucune différence. Il faut juste y accéder d'une manière un peu spéciale. On doit indiquer le nom du tableau et le numéro de la case. Dans le tableau meilleurScore, on a accès à cinq variables : la première case de meilleurScore, la deuxième, etc, jusqu'à la cinquième.

Pour accéder à une case, on utilise la syntaxe nomDuTableau[numeroDeLaCase]. Il y a simplement une petite subtilité : la première case possède le numéro 0 et pas 1. Tout est en quelque sorte décalé de 1. Pour accéder à la troisième case de meilleurScoreet y stocker une valeur, il faudra donc écrire :

meilleurScore[2] = 5;

En effet, $\(3-1=2\)$ ; la troisième case possède donc le numéro 2. Si je veux remplir mon tableau des meilleurs scores comme dans l'exemple initial, je peux donc écrire :

int const nombreMeilleursScores(5);           //La taille du tableau

int meilleursScores[nombreMeilleursScores];   //Déclaration du tableau

meilleursScores[0] = 118218;  //Remplissage de la première case
meilleursScores[1] = 100432;  //Remplissage de la deuxième case
meilleursScores[2] = 87347;   //Remplissage de la troisième case
meilleursScores[3] = 64523;   //Remplissage de la quatrième case
meilleursScores[4] = 31415;   //Remplissage de la cinquième case

Parcourez un tableau

Le gros point fort des tableaux, c'est qu'on peut les parcourir en utilisant une boucle. On peut ainsi effectuer une action sur chacune des cases d'un tableau, l'une après l'autre : par exemple afficher le contenu des cases.

On connaît a priori le nombre de cases du tableau, on peut donc utiliser une boucle for. Nous allons pouvoir utiliser la variable ide la boucle pour accéder au ième élément du tableau. C'est fou, on dirait que c'est fait pour !

int const nombreMeilleursScores(5);           //La taille du tableau
int meilleursScores[nombreMeilleursScores];   //Déclaration du tableau

meilleursScores[0] = 118218;  //Remplissage de la première case
meilleursScores[1] = 100432;  //Remplissage de la deuxième case
meilleursScores[2] = 87347;   //Remplissage de la troisième case
meilleursScores[3] = 64523;   //Remplissage de la quatrième case
meilleursScores[4] = 31415;   //Remplissage de la cinquième case

for(int i(0); i<nombreMeilleursScores; ++i)
{ 
    cout << meilleursScores[i] << endl;
}

La variableiprend successivement les valeurs 0, 1, 2, 3 et 4, ce qui veut dire que les valeurs demeilleursScores[0], puismeilleursScores[1], etc. sont envoyées danscout.

Vous allez voir, le couple tableau / boucleforva devenir votre nouveau meilleur ami. En tout cas, je l'espère : c'est un outil très puissant.

Un petit exemple

Allez, je vous propose un petit exemple légèrement plus complexe. Nous allons utiliser le C++ pour calculer la moyenne de vos notes de l'année. Je vous propose de mettre toutes vos notes dans un tableau et d'utiliser une boucle forpour le calcul de la moyenne. Voyons donc tout cela étape par étape.

La première étape consiste à déclarer un tableau pour stocker les notes. Comme ce sont des nombres à virgule, il nous faut des double.

int const nombreNotes(6);
double notes[nombreNotes];

La deuxième étape consiste à remplir ce tableau avec vos notes. J'espère que vous savez encore comment faire !

int const nombreNotes(6);
double notes[nombreNotes];

notes[0] = 12.5;
notes[1] = 19.5;  //Bieeeen !
notes[2] = 6.;    //Pas bien !
notes[3] = 12;
notes[4] = 14.5;
notes[5] = 15;

Pour calculer la moyenne, il nous faut additionner toutes les notes puis diviser le résultat obtenu par le nombre de notes. Nous connaissons déjà le nombre de notes, puisque nous avons la constante nombreNotes. Il ne reste donc qu'à déclarer une variable pour contenir la moyenne.

Le calcul de la somme s'effectue dans une boucle forqui parcourt toutes les cases du tableau.

double moyenne(0);
for(int i(0); i<nombreNotes; ++i)
{
   moyenne += notes[i];   //On additionne toutes les notes
}
//En arrivant ici, la variable moyenne contient la somme des notes (79.5)
//Il ne reste donc qu'à diviser par le nombre de notes
moyenne /= nombreNotes;

Avec une petite ligne pour l'affichage de la valeur, on obtient le résultat voulu : un programme qui calcule la moyenne de vos notes.

#include <iostream>
using namespace std;

int main()
{
   int const nombreNotes(6);
   double notes[nombreNotes];

   notes[0] = 12.5;
   notes[1] = 19.5;  //Bieeeen !
   notes[2] = 6.;    //Pas bien !
   notes[3] = 12;
   notes[4] = 14.5;
   notes[5] = 15;
   
   double moyenne(0);
   for(int i(0); i<nombreNotes; ++i)
   {
      moyenne += notes[i];   //On additionne toutes les notes
   }
   //En arrivant ici, la variable moyenne contient la somme des notes (79.5)
   //Il ne reste donc qu'à diviser par le nombre de notes
   moyenne /= nombreNotes;
   
   cout << "Votre moyenne est : " << moyenne << endl;

   return 0;
}

Voyons ce que cela donne quand on l'exécute :

Votre moyenne est : 13.25

Et cela marche ! Mais vous n'en doutiez pas, bien sûr ?

Les tableaux et les fonctions

Ah ! Les fonctions. Vous n'avez pas oublié ce que c'est j'espère. Il faut quand même que je vous en reparle un peu. Comme vous allez le voir, les tableaux et les fonctions ne sont pas les meilleurs amis du monde.

La première restriction est qu'on ne peut pas écrire une fonction qui renvoie un tableau statique. C'est impossible.

La deuxième restriction est qu'un tableau statique est toujours passé par référence. Et il n'y a pas besoin d'utiliser l'esperluette (&) : c'est fait automatiquement. Cela veut dire que, lorsqu'on passe un tableau à une fonction, cette dernière peut le modifier.

Voici donc une fonction qui reçoit un tableau en argument.

void fonction(double tableau[])
{
    //…
}

Mais ce n'est pas tout ! Très souvent, on veut parcourir le tableau, avec une boucle forpar exemple. Il nous manque une information cruciale. Vous voyez laquelle ?

La taille ! À l'intérieur de la fonction précédente, il n'y a aucun moyen de connaître la taille du tableau ! Il faut donc impérativement ajouter un deuxième argument contenant la taille. Cela donne :

void fonction(double tableau[], int tailleTableau)
{
    //…
}

Oui, je sais c'est ennuyeux. Mais il ne faut pas vous en prendre à moi, je n'ai pas créé le langage.

Pour vous entraîner, je vous propose d'écrire une fonction moyenne()qui calcule la moyenne des valeurs d'un tableau.

Voici ma version :

/*
 *  Fonction qui calcule la moyenne des éléments d'un tableau
 *  - tableau : Le tableau dont on veut la moyenne
 *  - tailleTableau : La taille du tableau
 */
double moyenne(double tableau[], int tailleTableau)
{
   double moyenne(0);
   for(int i(0); i<tailleTableau; ++i)
   {
      moyenne += tableau[i];   //On additionne toutes les valeurs
   }
   moyenne /= tailleTableau;

   return moyenne;
}

Assez parlé de ces tableaux. Passons à la suite.

Les tableaux dynamiques

Je vous avais dit que nous allions parler de deux sortes de tableaux : ceux dont la taille est fixée et ceux dont la taille peut varier, les tableaux dynamiques. Certaines choses sont identiques, ce qui va nous éviter de tout répéter.

Déclarez un tableau dynamique

La première différence se situe au tout début de votre programme. Il faut ajouter la ligne#include <vector>pour utiliser ces tableaux.

La deuxième grosse différence se situe dans la manière de déclarer un tableau. On utilise la syntaxe présentée :

Déclaration d'un vector

Par exemple, pour un tableau de 5 entiers, on écrit :

#include <iostream>
#include <vector> //Ne pas oublier !
using namespace std;

int main()
{
   vector<int> tableau(5);

   return 0;
}

Il faut ici remarquer trois choses :

  1. le type n'est pas le premier mot de la ligne, contrairement aux autres variables ;

  2. on utilise une notation bizarre avec un chevron ouvrant et un chevron fermant ;

  3. on écrit la taille entre parenthèses et non entre crochets.

Cela veut dire que les choses ne ressemblent pas vraiment aux tableaux statiques. Cependant, vous allez voir que, pour parcourir le tableau, le principe est similaire.
Mais avant cela, il y a deux astuces bien pratiques à savoir.

On peut directement remplir toutes les cases du tableau en ajoutant un deuxième argument entre les parenthèses :

vector<int> tableau(5, 3);  //Crée un tableau de 5 entiers valant tous 3
vector<string> listeNoms(12, "Sans nom");
//Crée un tableau de 12 strings valant toutes « Sans nom »

On peut déclarer un tableau sans cases en ne mettant pas de parenthèses du tout :

vector<double> tableau; //Crée un tableau de 0 nombre à virgule

Euh… À quoi sert un tableau vide ?

Rappelez-vous que ce sont des tableaux dont la taille peut varier. On peut donc ajouter des cases par la suite. Attendez un peu et vous saurez tout.

Accédez aux éléments d'un tableau

La déclaration était très différente des tableaux statiques. Par contre, l'accès est exactement identique. On utilise à nouveau les crochets et la première case possède aussi le numéro 0.

On peut donc réécrire l'exemple de la section précédente avec un vector :

int const nombreMeilleursScores(5);  //La taille du tableau

vector<int> meilleursScores(nombreMeilleursScores);  //Déclaration du tableau

meilleursScores[0] = 118218;  //Remplissage de la première case
meilleursScores[1] = 100432;  //Remplissage de la deuxième case
meilleursScores[2] = 87347;   //Remplissage de la troisième case
meilleursScores[3] = 64523;   //Remplissage de la quatrième case
meilleursScores[4] = 31415;   //Remplissage de la cinquième case

Là, je crois qu'on ne peut pas faire plus facile.

Changez la taille

Entrons maintenant dans le vif du sujet : faire varier la taille d'un tableau. Commençons par ajouter des cases à la fin d'un tableau.

Il faut utiliser la fonction push_back(). On écrit le nom du tableau, suivi d'un point et du mot push_backavec, entre parenthèses, la valeur qui va remplir la nouvelle case.

vector<int> tableau(3,2);  //Un tableau de 3 entiers valant tous 2
tableau.push_back(8);
//On ajoute une 4ème case au tableau qui contient la valeur 8

Voyons de plus près ce qui se passe dans la mémoire :

Effet d'un push_back sur un vector
Effet d'un push_back sur un vector

Une case supplémentaire a été ajoutée au bout du tableau, de manière automatique. C'est fou ce que cela peut être intelligent un ordinateur parfois.

Et bien sûr on peut ajouter beaucoup de cases à la suite les unes des autres.

vector<int> tableau(3,2); //Un tableau de 3 entiers valant tous 2
tableau.push_back(8);  //On ajoute une 4ème case qui contient la valeur 8
tableau.push_back(7);  //On ajoute une 5ème case qui contient la valeur 7
tableau.push_back(14); //Et encore une avec le nombre 14 cette fois

//Le tableau contient maintenant les nombres : 2 2 2 8 7 14

Et ils ne peuvent que grandir, les vectors ?

Non ! Bien sûr que non. Les créateurs du C++ ont pensé à tout.

On peut supprimer la dernière case d'un tableau en utilisant la fonctionpop_back()de la même manière quepush_back(), sauf qu'il n'y a rien à mettre entre les parenthèses.

vector<int> tableau(3,2); //Un tableau de 3 entiers valant tous 2
tableau.pop_back(); //Et hop ! Plus que 2 cases
tableau.pop_back(); //Et hop ! Plus que 1 case

Je crois que je n'ai pas besoin d'en dire plus sur ce sujet.

Il nous reste quand même un petit problème à régler. Comme la taille peut changer, on ne sait pas de manière certaine combien d'éléments contient un tableau. Heureusement, il y a une fonction pour cela :size(). Avectableau.size(), on récupère un entier correspondant au nombre d'éléments detableau.

vector<int> tableau(5,4); //Un tableau de 5 entiers valant tous 4
int const taille(tableau.size());
//Une variable qui contient la taille du tableau
//La taille peut varier mais la valeur de cette variable ne changera pas
//On utilise donc une constante
//À partir d'ici, la constante 'taille' vaut donc 5

Retour sur l'exercice

Je crois que le mieux, pour se mettre tout cela en tête, est de reprendre l'exercice du calcul des moyennes mais en le réécrivant à la « sauce vector ».

Je vous laisse essayer. Si vous n'y arrivez pas, voici ma solution :

#include <iostream>
#include <vector> //Ne pas oublier !
using namespace std;

int main()
{
   vector<double> notes; //Un tableau vide

   notes.push_back(12.5);  //On ajoute des cases avec les notes
   notes.push_back(19.5);
   notes.push_back(6);
   notes.push_back(12);
   notes.push_back(14.5);
   notes.push_back(15);
   
   double moyenne(0);
   for(int i(0); i<notes.size(); ++i)
   //On utilise notes.size() pour la limite de notre boucle
   {
      moyenne += notes[i];   //On additionne toutes les notes
   }

   moyenne /= notes.size();
   //On utilise à nouveau notes.size() pour obtenir le nombre de notes
   
   cout << "Votre moyenne est : " << moyenne << endl;

   return 0;
}

On a écrit deux programmes qui font exactement la même chose de deux manières différentes. C'est très courant, il y a presque toujours plusieurs manières de faire les choses. Chacun choisit celle qu'il préfère.

Lesvectoret les fonctions

Passer un tableau dynamique en argument à une fonction est beaucoup plus simple que pour les tableaux statiques. Comme pour n'importe quel autre type, il suffit de mettrevector<type>en argument. Et c'est tout. Grâce à la fonctionsize(), il n'y a même pas besoin d'ajouter un deuxième argument pour la taille du tableau !

Cela donne tout simplement :

//Une fonction recevant un tableau d'entiers en argument
void fonction(vector<int> a)
{
    //…
}

Simple non ? Mais on peut quand même faire mieux. Je vous ai parlé, au chapitre précédent, du passage par référence constante pour optimiser la copie. En effet, si le tableau contient beaucoup d'éléments, le copier prendra du temps. Il vaut donc mieux utiliser cette astuce, ce qui donne :

//Une fonction recevant un tableau d'entiers en argument
void fonction(vector<int> const& a)
{
    //…
}

Pour appeler une fonction recevant un vector en argument, il n'y a rien de particulier à faire. Comme dans le cas des variables du chapitre précédent, il suffit de mettre le nom du tableau dynamique comme paramètre entre les parenthèses lors de l'appel. Ce qui donne:

vector<int> tableau(3,2);   //On crée un tableau de 3 entiers valant 2
fonction(tableau);          //On passe le tableau à la fonction déclarée au-dessus

Si, comme moi, vous aimez découper votre programme en plusieurs fichiers en séparant les fichiers d'en-tête et les fichiers sources, il faudra penser à ajouter#include <vector>au début du fichier et std::devant les vector, comme pour les stringen fait:

#ifndef TABLEAU_H_INCLUDED
#define TABLEAU_H_INCLUDED

#include <vector>

void fonctionAvecTableau(std::vector<int>& tableau);

#endif // TABLEAU_H_INCLUDED

Il est évidemment possible d'écrire une fonction renvoyant un vector. Je suis sûr que vous avez déjà deviné comment déclarer une telle fonction. Par exemple pour une fonction qui renvoie un tableau multi-dimensionnels de nombres à virgule, on écrira:

vector<double> encoreUneFonction(int a)
{
    //...
}

Il faut, cependant, noter que ceci va implicitement générer une copie du tableau quand la fonction se termine. Pour éviter cela, on préfère utiliser un passage du tableau par référence, comme nous l'avons vu dans le chapitre précédent. Les copies inutiles de tableaux sont des sources courantes de ralentissement des programmes. Si vous avez besoin d'un programme très performant, faites attention à vos tableaux. ;)

Les tableaux multi-dimensionnels

Je vous ai dit en début de chapitre que l'on pouvait créer des tableaux de n'importe quoi. Des tableaux d'entiers, des tableaux de strings, et ainsi de suite. On peut donc créer des tableaux… de tableaux !

Je vous vois d'ici froncer les sourcils et vous demander à quoi cela peut bien servir. Une fois n'est pas coutume, je vous propose de commencer par visualiser la mémoire (figure suivante). Vous verrez peut-être l'intérêt de ce concept pour le moins bizarre.

Un tableau bi-dimensionnel dans la mémoire de l'ordinateur
Un tableau bi-dimensionnel dans la mémoire de l'ordinateur

La grosse case jaune représente, comme à chaque fois, une variable. Cette fois, c'est un tableau de 5 éléments dont j'ai représenté les cases en utilisant des lignes épaisses. À l'intérieur de chacune des cases, on trouve un petit tableau de 4 éléments dont on ne connaît pas la valeur.

Mais, si vous regardez attentivement les points d'interrogation, vous pouvez voir une grille régulière ! Un tableau de tableau est donc une grille de variables. Et là, je pense que vous trouvez cela tout de suite moins bizarre.

Déclaration d'un tableau multi-dimensionnel

Pour déclarer un tel tableau, il faut indiquer les dimensions les unes après les autres entre crochets :

type nomTableau[tailleX][tailleY]

Donc pour reproduire le tableau du schéma, on doit déclarer le tableau suivant :

int tableau[5][4];

Ou encore mieux, en déclarant des constantes :

int const tailleX(5);
int const tailleY(4);
int tableau[tailleX][tailleY];

Et c'est tout ! C'est bien le C++, non ?

Accédez aux éléments

Je suis sûr que je n'ai pas besoin de vous expliquer la suite. Vous avez sûrement deviné tout seul. Pour accéder à une case de notre grille, il faut indiquer la position en X et en Y de la case voulue.

Par exempletableau[0][0]accède à la case en-bas à gauche de la grille.tableau[0][1]correspond à celle qui se trouve juste au dessus, alors quetableau[1][0]se situe directement à sa droite.

Comment accéder à la case située en-haut à droite ?

Il s'agit de la dernière case dans la direction horizontale. Entre les premiers crochets, il faut donc mettre tailleX-1, c'est-à-dire 4. C'est également la dernière case selon l'axe vertical : par conséquent, entre les seconds crochets, il faut spécifier tailleY-1. Ainsi, cela donnetableau[4][3].

Allez plus loin

On peut bien sûr aller encore plus loin et créer des grilles tri-dimensionnelles, voire même plus. On peut tout à fait déclarer une variable comme ceci :

double grilleExtreme[5][4][6][2][7];

Mais là, il ne faudra pas me demander un dessin. Je vous rassure quand même, il est rare de devoir utiliser des grilles à plus de 3 dimensions. Ou alors, c'est que vous prévoyez de faire des programmes vraiment compliqués. Les grilles à 3D sont quand même assez courantes, pour des simulateurs 3D (avion, snowspeeder, etc. ;-) et pour tout ce qui touche à la physique : représentation de l'espace, d'une vitesse, d'une accélération, d'une force, d'un tenseur, etc.

Notez qu'il est aussi possible de créer des tableaux multi-dimensionnels de taille variable en utilisant les vectors. Pour une grille 2D d'entiers, on devra écrire :

vector<vector<int> > grille;

Le problème est que ce n'est pas réellement un tableau 2D, mais plutôt un tableau de lignes. Il faudra donc commencer par ajouter des lignes à notre tableau.

grille.push_back(vector<int>(5));   //On ajoute une ligne de 5 cases à notre grille
grille.push_back(vector<int>(3,4)); //On ajoute une ligne de 3 cases contenant chacune le nombre 4 à notre grille

Chaque ligne peut donc avoir une longueur différente. On peut accéder à une ligne en utilisant les crochets:

grille[0].push_back(8);     //Ajoute une case contenant 8 à la première ligne du tableau

Finalement, on peut accéder aux valeurs dans les cases de la grille en utilisant deux paires de crochets, comme pour les tableaux statiques. Il faut par contre s'assurer que cette ligne et cette colonne existent réellement.

grille[2][3] = 9;     //Change la valeur de la cellule (2,3) de la grille

Les strings comme tableaux

Avant de terminer ce chapitre, il faut quand même que je vous fasse une petite révélation. Les chaînes de caractères sont en fait des tableaux !

On ne le voit pas lors de la déclaration, c'est bien caché. Mais il s'agit en fait d'un tableau de lettres. Il y a même beaucoup de points communs avec lesvector.

Accédez aux lettres

L'intérêt de voir une chaîne de caractères comme un tableau de lettres, c'est qu'on peut accéder à ces lettres et les modifier. Et je ne vais pas vous surprendre, on utilise aussi les crochets.

#include <iostream>
#include <string>
using namespace std;

int main()
{
   string nomUtilisateur("Julien");
   cout << "Vous etes " << nomUtilisateur << "." <<endl;

   nomUtilisateur[0] = 'L';  //On modifie la première lettre
   nomUtilisateur[2] = 'c';  //On modifie la troisième lettre

   cout << "Ah non, vous etes " << nomUtilisateur << "!" << endl;

   return 0;
}

Testons pour voir :

Vous etes Julien.
Ah non, vous etes Lucien!

C'est fort ! Mais on peut faire encore mieux…

Les fonctions

On peut également utiliser size()pour connaître le nombre de lettres et push_back()pour ajouter des lettres à la fin. La encore, c'est comme avec vector.

string texte("Portez ce whisky au vieux juge blond qui fume.");  //46 caractères
cout << "Cette phrase contient " << texte.size() << " lettres." << endl;

Mais contrairement aux tableaux, on peut ajouter plusieurs lettres d'un coup. Et on utilise le +=.

#include <iostream>
#include <string>
using namespace std;

int main()
{
   string prenom("Albert"); 
   string nom("Einstein");
   
   string total;    //Une chaîne vide
   total += prenom; //On ajoute le prénom à la chaîne vide
   total += " ";    //Puis un espace
   total += nom;    //Et finalement le nom de famille

   cout << "Vous vous appelez " << total << "." << endl; 

   return 0;
}

Cela donne bien sûr :

Vous vous appelez Albert Einstein.

C'est fou ce que c'est bien le C++ parfois !

En résumé

  • Les tableaux sont des successions de variables en mémoire. Un tableau à 4 cases correspond donc en mémoire à 4 variables les unes à la suite des autres.

  • Un tableau s'initialise comme ceci :int meilleurScore[4];(pour 4 cases).

  • La première case est toujours numérotée 0 (meilleurScore[0]).

  • Si la taille du tableau est susceptible de varier, créez un tableau dynamique de type vector:vector<int> tableau(5);.

  • On peut créer des tableaux multi-dimensionnels. Par exemple, int tableau[5][4];revient à créer un tableau de 5 colonnes et 4 lignes.

  • Les chaînes de caractères stringpeuvent être considérées comme des tableaux. Chacune des cases correspond à un caractère.

Exemple de certificat de réussite
Exemple de certificat de réussite