Guide : Les Tableaux en C – Cas Particuliers
Les tableaux en langage C sont une structure de données fondamentale qui permet de gérer efficacement des collections d’éléments du même type. Ce guide aborde les cas particuliers et nuances dans la manipulation des tableaux.
1. Déclaration de tableaux avec tailles dynamiques
En C, la taille d’un tableau est généralement définie lors de sa déclaration. Cependant, une taille dynamique peut être spécifiée avec des pointeurs ou en utilisant une allocation dynamique.
Exemple :
#include <stdio.h>
#include <stdlib.h>
int main() {
int n;
printf("Entrez la taille du tableau : ");
scanf("%d", &n);
int *tableau = (int *)malloc(n * sizeof(int));
if (tableau == NULL) {
printf("Allocation mémoire échouée.\n");
return 1;
}
for (int i = 0; i < n; i++) {
tableau[i] = i * i;
}
for (int i = 0; i < n; i++) {
printf("tableau[%d] = %d\n", i, tableau[i]);
}
free(tableau);
return 0;
}
2. Tableaux multidimensionnels
Les tableaux à plusieurs dimensions sont utiles pour les matrices ou les grilles.
Exemple d’un tableau 2D :
#include <stdio.h>
int main() {
int tableau[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
printf("tableau[%d][%d] = %d\n", i, j, tableau[i][j]);
}
}
return 0;
}
3. Pointeurs et tableaux
Un tableau peut être manipulé via des pointeurs. Les noms de tableaux sont en réalité des pointeurs vers le premier élément.
Exemple avec pointeurs :
#include <stdio.h>
int main() {
int tableau[5] = {10, 20, 30, 40, 50};
int *ptr = tableau;
for (int i = 0; i < 5; i++) {
printf("Valeur à ptr[%d] = %d\n", i, *(ptr + i));
}
return 0;
}
4. Tableaux et fonctions
Les tableaux peuvent être passés en argument à une fonction. Cependant, seule l’adresse du premier élément est transmise, ce qui nécessite d’envoyer également la taille si besoin.
Exemple :
#include <stdio.h>
void afficherTableau(int tableau[], int taille) {
for (int i = 0; i < taille; i++) {
printf("tableau[%d] = %d\n", i, tableau[i]);
}
}
int main() {
int tableau[5] = {1, 2, 3, 4, 5};
afficherTableau(tableau, 5);
return 0;
}
5. Initialisation partielle
Un tableau peut être partiellement initialisé. Les valeurs non initialisées sont définies à 0
pour les tableaux statiques.
Exemple :
#include <stdio.h>
int main() {
int tableau[10] = {1, 2, 3};
for (int i = 0; i < 10; i++) {
printf("tableau[%d] = %d\n", i, tableau[i]);
}
return 0;
}
6. Tableaux constants
Les tableaux déclarés avec const
ne peuvent pas être modifiés après leur initialisation.
Exemple :
#include <stdio.h>
int main() {
const int tableau[3] = {1, 2, 3};
// tableau[0] = 10; // Erreur : modification d’un tableau constant.
for (int i = 0; i < 3; i++) {
printf("tableau[%d] = %d\n", i, tableau[i]);
}
return 0;
}
7. Tableaux de chaînes
Un tableau de chaînes est un tableau de pointeurs vers des chaînes de caractères.
Exemple :
#include <stdio.h>
int main() {
const char *tableau[] = {"Bonjour", "le", "monde"};
int taille = sizeof(tableau) / sizeof(tableau[0]);
for (int i = 0; i < taille; i++) {
printf("%s ", tableau[i]);
}
return 0;
}
8. Tableaux et mémoire partagée
Attention : la mémoire des tableaux déclarés dans une fonction est locale. Si vous devez conserver cette mémoire après la fin de la fonction, utilisez l’allocation dynamique.
Exemple incorrect :
int *creerTableau() {
int tableau[5] = {1, 2, 3, 4, 5};
return tableau; // Erreur : tableau local détruit après le retour.
}
Solution correcte :
#include <stdlib.h>
int *creerTableau() {
int *tableau = (int *)malloc(5 * sizeof(int));
for (int i = 0; i < 5; i++) {
tableau[i] = i + 1;
}
return tableau;
}
Les tableaux en C offrent une flexibilité remarquable mais nécessitent une gestion attentive de la mémoire et des indices. Ce guide couvre des cas pratiques et avancés pour tirer pleinement parti des tableaux dans vos programmes.
En C, la fonction malloc
(memory allocation) permet de créer des tableaux dynamiques, dont la taille peut être spécifiée à l’exécution. Contrairement aux tableaux statiques, leur taille n’est pas fixe et peut être ajustée en fonction des besoins de l’utilisateur ou du programme.
1. Utilisation de malloc
pour créer des tableaux dynamiques
Étapes :
- Déclarez un pointeur du type des éléments du tableau.
- Utilisez
malloc
pour allouer un bloc de mémoire suffisant pour contenir les éléments du tableau. - Vérifiez que l’allocation a réussi (le retour de
malloc
n’est pasNULL
). - Utilisez le tableau normalement avec l’opérateur d’indirection (
[]
). - Libérez la mémoire allouée avec
free
lorsque le tableau n’est plus nécessaire.
Exemple : Tableau 1D (1 dimension)
#include <stdio.h>
#include <stdlib.h>
int main() {
int n;
printf("Entrez la taille du tableau : ");
scanf("%d", &n);
// Allocation dynamique d'un tableau d'entiers
int *tableau = (int *)malloc(n * sizeof(int));
if (tableau == NULL) {
printf("Échec de l'allocation mémoire.\n");
return 1; // Quitte le programme en cas d'erreur
}
// Initialisation des éléments
for (int i = 0; i < n; i++) {
tableau[i] = i + 1;
}
// Affichage des éléments
printf("Éléments du tableau : ");
for (int i = 0; i < n; i++) {
printf("%d ", tableau[i]);
}
printf("\n");
// Libération de la mémoire
free(tableau);
return 0;
}
2. Utilisation de malloc
pour des tableaux multidimensionnels
Exemple : Tableau 2D (2 dimensions)
Il existe deux approches courantes pour gérer des tableaux 2D dynamiques avec malloc
.
Approche 1 : Allocation en une seule dimension
Les éléments sont alloués dans une seule grande zone mémoire, et l’accès aux éléments est géré manuellement.
#include <stdio.h>
#include <stdlib.h>
int main() {
int lignes, colonnes;
printf("Entrez le nombre de lignes et de colonnes : ");
scanf("%d %d", &lignes, &colonnes);
// Allocation d'un tableau 2D (linéarisé)
int *tableau = (int *)malloc(lignes * colonnes * sizeof(int));
if (tableau == NULL) {
printf("Échec de l'allocation mémoire.\n");
return 1;
}
// Initialisation et affichage
for (int i = 0; i < lignes; i++) {
for (int j = 0; j < colonnes; j++) {
tableau[i * colonnes + j] = i + j; // Accès avec une formule
printf("%d ", tableau[i * colonnes + j]);
}
printf("\n");
}
// Libération de la mémoire
free(tableau);
return 0;
}
Approche 2 : Allocation ligne par ligne
Chaque ligne est allouée séparément, ce qui donne une meilleure flexibilité mais requiert une gestion supplémentaire.
#include <stdio.h>
#include <stdlib.h>
int main() {
int lignes, colonnes;
printf("Entrez le nombre de lignes et de colonnes : ");
scanf("%d %d", &lignes, &colonnes);
// Allocation d'un tableau de pointeurs
int **tableau = (int **)malloc(lignes * sizeof(int *));
if (tableau == NULL) {
printf("Échec de l'allocation mémoire.\n");
return 1;
}
// Allocation pour chaque ligne
for (int i = 0; i < lignes; i++) {
tableau[i] = (int *)malloc(colonnes * sizeof(int));
if (tableau[i] == NULL) {
printf("Échec de l'allocation mémoire pour la ligne %d.\n", i);
return 1;
}
}
// Initialisation et affichage
for (int i = 0; i < lignes; i++) {
for (int j = 0; j < colonnes; j++) {
tableau[i][j] = i * j; // Accès direct
printf("%d ", tableau[i][j]);
}
printf("\n");
}
// Libération de la mémoire
for (int i = 0; i < lignes; i++) {
free(tableau[i]); // Libère chaque ligne
}
free(tableau); // Libère le tableau de pointeurs
return 0;
}
3. Cas particulier : Redimensionner un tableau avec realloc
Si vous avez besoin d’agrandir ou de réduire la taille d’un tableau alloué dynamiquement, utilisez realloc
.
Exemple :
#include <stdio.h>
#include <stdlib.h>
int main() {
int n;
printf("Entrez la taille initiale du tableau : ");
scanf("%d", &n);
int *tableau = (int *)malloc(n * sizeof(int));
if (tableau == NULL) {
printf("Échec de l'allocation mémoire.\n");
return 1;
}
// Initialisation
for (int i = 0; i < n; i++) {
tableau[i] = i + 1;
}
// Augmenter la taille du tableau
printf("Entrez la nouvelle taille du tableau : ");
int nouveau_n;
scanf("%d", &nouveau_n);
tableau = (int *)realloc(tableau, nouveau_n * sizeof(int));
if (tableau == NULL) {
printf("Échec de l'allocation mémoire.\n");
return 1;
}
// Initialisation des nouveaux éléments
for (int i = n; i < nouveau_n; i++) {
tableau[i] = i + 1;
}
// Affichage
printf("Éléments du tableau redimensionné : ");
for (int i = 0; i < nouveau_n; i++) {
printf("%d ", tableau[i]);
}
printf("\n");
// Libération
free(tableau);
return 0;
}
4. Bonnes pratiques avec malloc
- Toujours vérifier que
malloc
a réussi (le pointeur n’est pasNULL
). - Libérer la mémoire avec
free
dès qu’elle n’est plus nécessaire pour éviter les fuites de mémoire. - En cas d’échec de l’allocation avec
malloc
, assurez-vous que le programme gère proprement l’erreur (par exemple, en affichant un message ou en sortant du programme).
Avec ces notions, vous pouvez utiliser malloc
efficacement pour gérer des tableaux dynamiques en C !