Un tableau à deux dimensions (couramment appelé matrice ou grille) permet de structurer des données selon un agencement bidimensionnel composé de lignes et de colonnes.
C'est la structure idéale pour représenter des jeux de plateau (échecs, dames, morpion), des grilles d'images numériques (pixels organisés en largeur et hauteur) ou des tableaux statistiques de scores.
1. Représentation conceptuelle et mémoire physique#
Mathématiquement, une matrice \(A\) de dimension \(3 \times 4\) (3 lignes et 4 colonnes) s'écrit :
Comment la mémoire RAM stocke-t-elle une matrice ?#
La mémoire physique d'un ordinateur est un ruban linéaire unidimensionnel. Pour stocker un tableau 2D, le langage C utilise la convention de l'ordre ligne par ligne (Row-Major Order) : la première ligne complète est stockée, suivie immédiatement de la deuxième, puis de la troisième :
flowchart LR
subgraph RAM [Disposition Row-Major en RAM]
L0["Ligne 0 : [A00] [A01] [A02] [A03]"] --- L1["Ligne 1 : [A10] [A11] [A12] [A13]"]
L1 --- L2["Ligne 2 : [A20] [A21] [A22] [A23]"]
end
L'adresse de l'élément à la ligne \(i\) et colonne \(j\) est calculée par la formule : $\(\text{Position\_Linéaire} = i \times \text{Nombre\_de\_Colonnes} + j\)$
[!NOTE] C'est pour cette raison exacte que lors du passage d'une matrice à une fonction, le compilateur C exige obligatoirement de connaître le nombre de colonnes : sans cette information, il est incapable de calculer à quel endroit en mémoire commence chaque nouvelle ligne !
2. Déclaration et Initialisation#
Déclaration d'une matrice#
#define LIGNES 3
#define COLONNES 4
// Déclare une matrice de 3 lignes et 4 colonnes (12 cases au total)
int grille[LIGNES][COLONNES];
Méthodes d'initialisation#
// 1. Initialisation par blocs de lignes avec accolades imbriquées (LISIBLE)
int matrice[2][3] = {
{10, 20, 30}, // Ligne 0
{40, 50, 60} // Ligne 1
};
// 2. Initialisation intégrale à zéro (TRÈS PRATIQUE)
int grille_nulle[3][3] = {0};
// 3. Déduction automatique du nombre de lignes (les colonnes restent obligatoires)
int tab[][3] = {
{1, 2, 3},
{4, 5, 6}
}; // Déduit automatiquement 2 lignes
3. Parcours complet : Saisie et Affichage avec boucles imbriquées#
Pour manipuler chaque cellule d'une matrice, on utilise deux boucles for imbriquées :
- L'indice extérieur i parcourt les lignes (de 0 à LIGNES - 1).
- L'indice intérieur j parcourt les colonnes (de 0 à COLONNES - 1).
#include <stdio.h>
#define N 3
#define M 3
int main(void)
{
int matrice[N][M];
// 1. Saisie des éléments
printf("--- SAISIE D'UNE MATRICE %d x %d ---\n", N, M);
for (int i = 0; i < N; i++)
{
for (int j = 0; j < M; j++)
{
printf("Element [%d][%d] : ", i, j);
scanf("%d", &matrice[i][j]);
}
}
// 2. Affichage sous forme de tableau
printf("\n--- VISUALISATION DE LA MATRICE ---\n");
for (int i = 0; i < N; i++)
{
printf("| ");
for (int j = 0; j < M; j++)
{
printf("%4d ", matrice[i][j]); // Aligné sur 4 caractères
}
printf("|\n"); // Saut de ligne à la fin de chaque rangée
}
return 0;
}
4. Transmettre une matrice à une fonction#
Comme mentionné plus haut, la signature d'une fonction recevant une matrice 2D doit impérativement spécifier la taille de la seconde dimension (les colonnes) :
#include <stdio.h>
#define NB_LIGNES 2
#define NB_COLS 3
// Le nombre de colonnes NB_COLS est obligatoire entre les deuxièmes crochets !
void AfficherMatrice(const int mat[][NB_COLS], int nbLignes)
{
for (int i = 0; i < nbLignes; i++)
{
printf("[ ");
for (int j = 0; j < NB_COLS; j++)
{
printf("%d ", mat[i][j]);
}
printf("]\n");
}
}
int main(void)
{
int test[NB_LIGNES][NB_COLS] = {
{1, 2, 3},
{4, 5, 6}
};
AfficherMatrice(test, NB_LIGNES);
return 0;
}
5. Mise en pratique : Générateur de Matrice Identité (\(I_n\))#
Une matrice identité \(I_n\) est une matrice carrée comportant des 1 sur sa diagonale principale (\(i == j\)) et des 0 partout ailleurs (\(i \ne j\)).
#include <stdio.h>
#define TAILLE 4
int main(void)
{
int identite[TAILLE][TAILLE] = {0};
// Construction de la matrice identité
for (int i = 0; i < TAILLE; i++)
{
for (int j = 0; j < TAILLE; j++)
{
if (i == j)
{
identite[i][j] = 1; // Diagonale principale
}
}
}
// Affichage
printf("Matrice Identite I_%d :\n", TAILLE);
for (int i = 0; i < TAILLE; i++)
{
for (int j = 0; j < TAILLE; j++)
{
printf("%d ", identite[i][j]);
}
printf("\n");
}
return 0;
}
Vous maîtrisez la structure et la manipulation des matrices 2D. Dans le chapitre suivant, nous allons implémenter les opérations reines de l'algèbre linéaire : l'addition, la transposée et le produit matriciel.
Commentaires