Les tableaux multi-dimensionnels
===
###### tags: `algo` `bourg` `c++` `iut` `cm`
Le cours en video:
{%youtube 49TsMN_Xpn0 %}
Jusqu'à présent, nous avons vu les tableaux à une seule dimension. Comme dans de nombreux langages de programmation, il est possible en C++ de définir des tableaux à plusieurs dimensions. Ceux-ci sont très utilisés, par exemple pour modéliser des matrices, des images, des données à plusieurs paramètres...
### Déclaration et utilisation d'un tableau à plusieurs dimensions
La déclaration est similaire à un tableau unidimensionnel, sauf que l'on utilisera des crochets pour donner la taille de chacune des dimensions. Par exemple la déclaration
```C++
int tabi[4][7];
```
définit un tableau d'entiers à deux dimensions, de taille $4\times 7$ (soit $28$ cases). Généralement, on représente de tels tableaux graphiquement par une grille (ou une matrice) avec $4$ lignes et $7$ colonnes, comme sur la figure ci-dessous. Pour les tableaux à deux dimensions, on utilisera souvent $i$ comme indice pour les lignes, et $j$ pour les colonnes.
| ``tabi`` | $j=0$ | $j=1$ | $j=2$ | $j=3$ | $j=4$ | $j=5$ | $j=6$ |
| ---- | --- | --- | --- | --- | --- | --- | --- |
| $i=0$ | | | | | | | |
| $i=1$ | | | | | | | |
| $i=2$ | | | | | | | |
| $i=3$ | | | | | | | |
La déclaration
```C++
bool tabb [4][7][3][2];
````
définit un tableau de booléens à quatre dimensions, de taille $4\times 7\times 3\times 2$ (comportant donc 168 cases).
Comme pour les tableaux 1D, les indices utilisés pour accéder aux cases du tableau vont de $0$ à $taille-1$, où $taille$ est la taille de chacune des dimensions. Une case du tableau doit être repérée par autant d'indices qu'il y a de dimensions.
Par exemple, pour les tableaux déclarés ci-dessus, les notations suivantes ont du sens:
``tabi[3][5]`` et ``tabb[2][0][2][1]``.
Par conséquent, si l'on souhaite initialiser le tableau ``tabi`` ci-dessus avec des zéros, les lignes ci-dessous avec deux boucles imbriquées (attention aux bornes) réalisent l'opération demandée :
```C++
int i,j;
for (i=0;i<4;i++){ // parcours des 4 lignes
for (j=0;j<7;j++){ // parcours des 7 colonnes
tabi[i][j]=0;
}
}
````
:::info
De manière générale, pensez que pour parcourir toutes les cases d'un tableau à $k$ dimensions, une structure avec $k$ boucles imbriquées est une technique habituelle.
:::
### Initialisation
Il est également possible d'initialiser un tableau en même temps que sa déclaration. Comme pour les tableaux à une dimension, on utilise une notation avec des accolades. Par exemple pour un tableau $3 \times 4$:
````C++
int tab[3][4]={ {2 ,5 ,6 , -2} , // valeurs sur ligne 1
{1 ,3 , -5 ,8} , // valeurs sur ligne 2
{4 ,7 ,8 ,12} } ; // valeurs sur ligne 3
````
:::danger
Comme pour les tableaux 1D, on ne peut pas utiliser l'initialisation avec les accolades autrement qu'au moment de la déclaration. Par exemple, le code ci-dessous est LE MAL.
````C++
int tab[2][4];
...
tab={ {2 ,5 ,6 ,-2} ,
{1 ,3 ,-5 ,8} }
````
Donc pas le choix: si vous voulez initialiser votre tableau à un autre moment que la déclaration, il faudra le faire case à case (du genre ``tab[0][0]=2; tab[0][1]=5; ...``).
:::
### Passage d'un tableau multidimensionnel en paramètre d'une fonction
On peut passer un tableau multidimensionnel en paramètre d'une fonction. Là encore, les propriétés vues pour les tableaux 1D restent valables, en particulier le fait que le passage par référence est inutile pour modifier les cases du tableau.
En revanche, si pour un tableau 1D il est facultatif de mettre la taille du tableau dans le prototype de la fonction, il est obligatoire pour un tableau à $k$ dimensions de donner les tailles des $(k - 1)$ dernières dimensions dans le prototype. Cela donne par exemple:
````c++
void f(int tab [][4][2]) ;
````
Une entête du type void ``f(int tab[][])`` ou encore ``f(int tab[4][2][])`` serait donc rejetée. En revanche, il est aussi possible de donner les tailles de toutes les dimensions du tableau.