# Les Tableaux en C
Les tableaux (ou *arrays* en anglais) sont une structure de données essentielle, omniprésente dans le développement logiciel. Ils vous permettront de manipuler des **collections** de données de manière structurée et efficace. Forts de vos connaissances en algorithmique, vous reconnaîtrez rapidement l'utilité des tableaux pour représenter des listes, des séquences ou même des grilles d'informations.
# 1. Qu'est-ce qu'un tableaux
> [!definition] Qu'est-ce qu'un tableau ?
> Un **tableau** (ou *array* en anglais) est une collection contiguë d'éléments de même type stockés en mémoire. Chaque élément est accessible via un **indice** numérique, qui représente sa position relative au début du tableau. En C, les indices commencent toujours à **0**.
Imaginez que vous ayez besoin de stocker les notes de 30 étudiants, les températures quotidiennes d'un mois, ou les coordonnées d'une série de points dans un espace 2D. Plutôt que de déclarer 30 variables individuelles (`note1`, `note2`, ..., `note30`), un tableau `notes`vous offre une solution élégante et extensible pour regrouper ces données sous un nom unique.
Imaginez une série de boîtes alignées, toutes de la même taille, et chacune pouvant contenir une note. Pour accéder à une boîte spécifique, vous indiquez son décalage relativement à la première boite (donc 0, si c'est la note de la première boite qui vous intéresse).
# 2. Déclaration d'un tableau unidimensionnel
Pour utiliser un tableau en C, il faut d'abord le déclarer. La déclaration spécifie le type des éléments que le tableau contiendra et sa taille (le nombre d'éléments qu'il peut stocker).
> [!syntax] Syntaxe de déclaration
> ```c
> type nom_du_tableau[taille];
> ```
> - `type` : Le type de données des éléments du tableau (ex: `int`, `float`, `char`, `double`, etc.).
> - `nom_du_tableau` : L'identifiant du tableau.
> - `taille` : Une expression entière constante qui spécifie le nombre d'éléments que le tableau peut contenir.
> [!example] Exemples de déclaration
> ```c
> int notes[5]; // Déclare un tableau de 5 entiers
> float temperatures[30]; // Déclare un tableau de 30 nombres flottants
> char nom[50]; // Déclare un tableau de 50 caractères
> ```
> [!warning] Taille du tableau
> En C standard (C99 et ultérieur), la taille d'un tableau peut être une variable si elle est déterminée à l'exécution (on parle de *Variable Length Arrays* ou VLA). Cependant, pour des raisons de portabilité et de bonnes pratiques (surtout dans un contexte embarqué ou de performance), il est souvent préférable d'utiliser des **constantes** pour définir la taille des tableaux, ou d'allouer la mémoire dynamiquement (ce que nous verrons avec les pointeurs).
>
> ```c
> #define MAX_ELEMENTS 100
> int data[MAX_ELEMENTS]; // Taille définie par une constante symbolique
>
> // Ou avec const (si la taille est connue à la compilation)
> const int TAILLE_BUFFER = 256;
> char buffer[TAILLE_BUFFER];
> ```
# 3. Initialisation des Tableaux
Lorsqu'un tableau est déclaré, ses éléments contiennent des "valeurs parasites" (ou *garbage values*) s'il n'est pas initialisé. Il est crucial d'initialiser un tableau avant de l'utiliser.
## 3.1 Initialisation à la déclaration
Il est possible d'initialiser un tableau au moment de sa déclaration en fournissant une liste de valeurs entre accolades `{}`.
> [!example] Initialisation complète
> ```c
> int nombres_premiers[5] = {2, 3, 5, 7, 11};
> // Le tableau 'nombres_premiers' contient maintenant les valeurs spécifiées.
> // nombres_premiers[0] est 2, nombres_premiers[1] est 3, etc.
> ```
Si vous fournissez moins de valeurs que la taille spécifiée, les éléments restants sont initialisés à **zéro** (pour les types numériques) ou au caractère nul `\0` (pour les `char`).
> [!example] Initialisation partielle
> ```c
> int ages[10] = {20, 22, 25};
> // ages[0] = 20, ages[1] = 22, ages[2] = 25
> // ages[3] à ages[9] seront tous initialisés à 0
> ```
Vous pouvez laisser le compilateur déterminer la taille du tableau en omettant la taille lors de la déclaration et en fournissant une liste d'initialisation.
> [!example] Taille implicite
> ```c
> float poids[] = {65.5, 72.1, 80.0, 58.9};
> // Le compilateur détermine que 'poids' est un tableau de 4 flottants.
> // poids[0] = 65.5, poids[1] = 72.1, etc.
> ```
## 3.2 Initialisation après la déclaration
Si vous ne pouvez pas initialiser le tableau à la déclaration, vous devrez le faire ultérieurement, souvent à l'aide d'une boucle.
> [!example] Initialisation avec une boucle
> ```c
> #include <stdio.h>
>
> int main() {
> int tableau[10];
> int i;
>
> // Initialiser tous les éléments à 0
> for (i = 0; i < 10; i++) {
> tableau[i] = 0;
> }
>
> // Initialiser avec des valeurs spécifiques (ex: les 10 premiers entiers)
> for (i = 0; i < 10; i++) {
> tableau[i] = i; // tableau[0]=0, tableau[1]=1, ..., tableau[9]=9
> }
>
> return 0;
> }
> ```
# 4. Accès aux Éléments d'un Tableau
Chaque élément d'un tableau est accessible individuellement en utilisant son nom suivi de son indice entre crochets `[]`.
## 4.1 Indexation
En C, les tableaux sont **indexés à partir de 0**. Cela signifie que le premier élément est à l'indice 0, le deuxième à l'indice 1, et ainsi de suite jusqu'à l'indice `taille - 1`.
> [!theorem] Plage d'indices
> Pour un tableau `T` de taille $N$, les indices valides vont de $0$ à $N-1$.
>
> Si un tableau est déclaré comme `type T[N];`, alors les éléments sont :
> $T[0], T[1], \dots, T[N-1]$.
> [!example] Accès et modification
> ```c
> #include <stdio.h>
>
> int main() {
> int scores[3] = {100, 85, 92};
>
> // Accéder et afficher le premier élément
> printf("Le premier score est : %d\n", scores[0]); // Affiche 100
>
> // Modifier le deuxième élément
> scores[1] = 90;
> printf("Le deuxième score est maintenant : %d\n", scores[1]); // Affiche 90
>
> // Accéder au dernier élément (indice 2 pour un tableau de taille 3)
> printf("Le dernier score est : %d\n", scores[2]); // Affiche 92
>
> return 0;
> }
> ```
## 4.2 Parcours de tableau avec des boucles
Les boucles sont l'outil idéal pour parcourir et manipuler tous les éléments d'un tableau.
> [!example] Parcourir et afficher un tableau
> ```c
> #include <stdio.h>
>
> int main() {
> int notes_eleves[5] = {15, 12, 18, 9, 14};
> int i;
>
> printf("Les notes des élèves sont :\n");
> for (i = 0; i < 5; i++) {
> printf("Élève %d : %d/20\n", i + 1, notes_eleves[i]);
> }
>
> // Calculer la moyenne
> int somme = 0;
> for (i = 0; i < 5; i++) {
> somme += notes_eleves[i];
> }
> float moyenne = (float)somme / 5;
> printf("La moyenne de la classe est : %.2f\n", moyenne);
>
> return 0;
> }
> ```
> [!warning] Dépassement d'indice (Out-of-bounds access)
> Le langage C ne réalise **aucune vérification automatique des bornes** lors de l'accès aux éléments d'un tableau. Si vous tentez d'accéder à `scores[3]` pour un tableau `scores` de taille 3 (indices valides 0, 1, 2), le compilateur ne signalera pas d'erreur. Cela entraînera un comportement indéfini (lecture/écriture dans une zone mémoire non allouée au tableau), pouvant causer des plantages du programme ou des vulnérabilités de sécurité. C'est une source très fréquente de bugs en C.
>
> Il est de la responsabilité du programmeur de s'assurer que les indices utilisés sont toujours valides.
# Conclusion et perspectives