Langage C/C++

Tableaux en Langage C : Exercices Corrigés

📚 Guide complet de programmation en langage C

Tableaux en C : cours pratique, exemples et exercices corrigés

Maîtrisez les tableaux à une dimension, les tableaux multidimensionnels, les tableaux dynamiques, les fonctions manipulant des tableaux, les pointeurs, les allocations mémoire ainsi que les principales techniques utilisées dans les applications professionnelles grâce à des explications détaillées, des programmes complets, des cas pratiques et de nombreux exercices corrigés.

📦

Tableaux statiques

Déclaration, initialisation, parcours, recherche, tri, copie et manipulation des tableaux classiques.

🧮

Matrices

Tableaux à deux dimensions, matrices, affichage, calculs, parcours ligne par ligne et applications numériques.

Tableaux dynamiques

malloc(), calloc(), realloc(), free(), redimensionnement, gestion de la mémoire et bonnes pratiques.

💻

Exercices corrigés

Exercices progressifs, programmes commentés, solutions détaillées et erreurs fréquentes expliquées.

✔ Déclaration des tableaux   •   ✔ Initialisation   •   ✔ Parcours avec les boucles   •   ✔ Fonctions manipulant les tableaux   •   ✔ Tableaux de chaînes de caractères   •   ✔ Matrices   •   ✔ Pointeurs et tableaux   •   ✔ Allocation dynamique   •   ✔ Cas pratiques   •   ✔ Exercices corrigés

Créer et gérer un tableau dynamique en C

Un tableau dynamique est créé pendant l’exécution du programme. Sa taille peut dépendre d’une saisie utilisateur, d’un fichier ou d’un calcul. Sa mémoire est réservée avec malloc, modifiée avec realloc puis libérée avec free.

Principe : contrairement à un tableau classique, la taille d’un tableau dynamique peut être déterminée pendant l’exécution du programme.
Exemple simple — Créer un tableau dynamique avec malloc

La fonction malloc réserve une zone mémoire suffisamment grande pour contenir le nombre d’éléments demandé.

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int taille;

    printf("Nombre d'elements : ");
    scanf("%d", &taille);

    if (taille <= 0)
    {
        printf("La taille doit etre positive.\n");
        return 1;
    }

    int *tableau = malloc((size_t)taille * sizeof(int));

    if (tableau == NULL)
    {
        fprintf(stderr, "Erreur d'allocation memoire.\n");
        return 1;
    }

    for (int i = 0; i < taille; i++)
    {
        tableau[i] = (i + 1) * 10;
    }

    printf("Contenu du tableau :\n");

    for (int i = 0; i < taille; i++)
    {
        printf("tableau[%d] = %d\n", i, tableau[i]);
    }

    free(tableau);
    tableau = NULL;

    return 0;
}
Le tableau est créé uniquement après que sa taille a été déterminée.
Saisir les valeurs du tableau dynamique

Chaque case du tableau peut être remplie à partir d’une saisie utilisateur.

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int taille;

    printf("Taille du tableau : ");
    scanf("%d", &taille);

    if (taille <= 0)
    {
        printf("Taille invalide.\n");
        return 1;
    }

    int *tableau = malloc((size_t)taille * sizeof(int));

    if (tableau == NULL)
    {
        fprintf(stderr, "Allocation impossible.\n");
        return 1;
    }

    for (int i = 0; i < taille; i++)
    {
        printf("Valeur %d : ", i + 1);
        scanf("%d", &tableau[i]);
    }

    printf("\nValeurs saisies : ");

    for (int i = 0; i < taille; i++)
    {
        printf("%d ", tableau[i]);
    }

    printf("\n");

    free(tableau);
    tableau = NULL;

    return 0;
}
Créer le tableau dans une fonction

Une fonction peut créer un tableau dynamique puis retourner son adresse.

#include <stdio.h>
#include <stdlib.h>

int *creerTableau(int taille)
{
    if (taille <= 0)
    {
        return NULL;
    }

    int *tableau = malloc((size_t)taille * sizeof(int));

    if (tableau == NULL)
    {
        return NULL;
    }

    for (int i = 0; i < taille; i++)
    {
        tableau[i] = i + 1;
    }

    return tableau;
}

int main(void)
{
    int taille = 5;
    int *valeurs = creerTableau(taille);

    if (valeurs == NULL)
    {
        fprintf(stderr, "Impossible de creer le tableau.\n");
        return 1;
    }

    for (int i = 0; i < taille; i++)
    {
        printf("%d ", valeurs[i]);
    }

    free(valeurs);
    valeurs = NULL;

    return 0;
}
La fonction qui reçoit le pointeur retourné devient responsable de la libération de la mémoire avec free.
Initialiser un tableau dynamique avec calloc

La fonction calloc réserve la mémoire et initialise automatiquement tous les octets à zéro.

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int taille = 6;

    int *tableau = calloc((size_t)taille, sizeof(int));

    if (tableau == NULL)
    {
        fprintf(stderr, "Erreur d'allocation.\n");
        return 1;
    }

    for (int i = 0; i < taille; i++)
    {
        printf("tableau[%d] = %d\n", i, tableau[i]);
    }

    free(tableau);
    tableau = NULL;

    return 0;
}
Avec calloc, les éléments numériques commencent généralement à zéro.
Agrandir un tableau dynamique avec realloc

La fonction realloc permet de modifier la taille d’une zone mémoire déjà allouée.

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int ancienneTaille = 3;
    int nouvelleTaille = 6;

    int *tableau = malloc(
        (size_t)ancienneTaille * sizeof(int)
    );

    if (tableau == NULL)
    {
        fprintf(stderr, "Erreur d'allocation.\n");
        return 1;
    }

    for (int i = 0; i < ancienneTaille; i++)
    {
        tableau[i] = (i + 1) * 10;
    }

    int *temporaire = realloc(
        tableau,
        (size_t)nouvelleTaille * sizeof(int)
    );

    if (temporaire == NULL)
    {
        free(tableau);
        fprintf(stderr, "Erreur pendant realloc.\n");
        return 1;
    }

    tableau = temporaire;

    for (int i = ancienneTaille; i < nouvelleTaille; i++)
    {
        tableau[i] = (i + 1) * 10;
    }

    for (int i = 0; i < nouvelleTaille; i++)
    {
        printf("%d ", tableau[i]);
    }

    free(tableau);
    tableau = NULL;

    return 0;
}
Il est préférable de stocker temporairement le résultat de realloc. Une affectation directe pourrait faire perdre l’adresse initiale en cas d’échec.
Structure complète — Tableau dynamique redimensionnable

Cette version regroupe le pointeur, la taille utilisée et la capacité totale dans une structure.

#include <stdio.h>
#include <stdlib.h>

typedef struct
{
    int *donnees;
    size_t taille;
    size_t capacite;
} TableauDynamique;

int initialiserTableau(
    TableauDynamique *tableau,
    size_t capaciteInitiale
)
{
    if (tableau == NULL || capaciteInitiale == 0)
    {
        return 0;
    }

    tableau->donnees = malloc(
        capaciteInitiale * sizeof(int)
    );

    if (tableau->donnees == NULL)
    {
        tableau->taille = 0;
        tableau->capacite = 0;
        return 0;
    }

    tableau->taille = 0;
    tableau->capacite = capaciteInitiale;

    return 1;
}

int ajouterValeur(
    TableauDynamique *tableau,
    int valeur
)
{
    if (tableau == NULL)
    {
        return 0;
    }

    if (tableau->taille == tableau->capacite)
    {
        size_t nouvelleCapacite =
            tableau->capacite * 2;

        int *temporaire = realloc(
            tableau->donnees,
            nouvelleCapacite * sizeof(int)
        );

        if (temporaire == NULL)
        {
            return 0;
        }

        tableau->donnees = temporaire;
        tableau->capacite = nouvelleCapacite;
    }

    tableau->donnees[tableau->taille] = valeur;
    tableau->taille++;

    return 1;
}

void afficherTableau(
    const TableauDynamique *tableau
)
{
    if (tableau == NULL)
    {
        return;
    }

    printf("Tableau : ");

    for (size_t i = 0; i < tableau->taille; i++)
    {
        printf("%d ", tableau->donnees[i]);
    }

    printf("\n");
}

void libererTableau(
    TableauDynamique *tableau
)
{
    if (tableau == NULL)
    {
        return;
    }

    free(tableau->donnees);

    tableau->donnees = NULL;
    tableau->taille = 0;
    tableau->capacite = 0;
}

int main(void)
{
    TableauDynamique tableau;

    if (!initialiserTableau(&tableau, 2))
    {
        fprintf(stderr, "Initialisation impossible.\n");
        return 1;
    }

    ajouterValeur(&tableau, 10);
    ajouterValeur(&tableau, 20);
    ajouterValeur(&tableau, 30);
    ajouterValeur(&tableau, 40);
    ajouterValeur(&tableau, 50);

    afficherTableau(&tableau);

    printf("Taille : %zu\n", tableau.taille);
    printf("Capacite : %zu\n", tableau.capacite);

    libererTableau(&tableau);

    return 0;
}
Lorsque la capacité est atteinte, le tableau est automatiquement agrandi. Cette organisation ressemble au fonctionnement d’un vecteur dynamique.
Supprimer un élément du tableau dynamique

Pour supprimer un élément, les valeurs situées après sa position sont décalées vers la gauche.

int supprimerValeur(
    TableauDynamique *tableau,
    size_t position
)
{
    if (tableau == NULL || position >= tableau->taille)
    {
        return 0;
    }

    for (size_t i = position; i + 1 < tableau->taille; i++)
    {
        tableau->donnees[i] =
            tableau->donnees[i + 1];
    }

    tableau->taille--;

    return 1;
}

Exemple d’utilisation

supprimerValeur(&tableau, 1);

afficherTableau(&tableau);
Supprimer un élément ne réduit pas automatiquement la capacité mémoire du tableau.
Cas particulier — Tableau dynamique à deux dimensions

Une matrice dynamique peut être créée sous la forme d’un tableau de pointeurs.

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int lignes = 3;
    int colonnes = 4;

    int **matrice = malloc(
        (size_t)lignes * sizeof(int *)
    );

    if (matrice == NULL)
    {
        return 1;
    }

    for (int i = 0; i < lignes; i++)
    {
        matrice[i] = malloc(
            (size_t)colonnes * sizeof(int)
        );

        if (matrice[i] == NULL)
        {
            for (int j = 0; j < i; j++)
            {
                free(matrice[j]);
            }

            free(matrice);
            return 1;
        }
    }

    for (int i = 0; i < lignes; i++)
    {
        for (int j = 0; j < colonnes; j++)
        {
            matrice[i][j] = i + j;
        }
    }

    for (int i = 0; i < lignes; i++)
    {
        for (int j = 0; j < colonnes; j++)
        {
            printf("%d ", matrice[i][j]);
        }

        printf("\n");
    }

    for (int i = 0; i < lignes; i++)
    {
        free(matrice[i]);
    }

    free(matrice);
    matrice = NULL;

    return 0;
}
Chaque ligne doit être libérée séparément avant de libérer le tableau principal de pointeurs.
Erreurs fréquentes avec les tableaux dynamiques
Erreur Conséquence Correction
Ne pas tester malloc Utilisation possible d’un pointeur nul Vérifier que le résultat est différent de NULL
Oublier free Fuite de mémoire Libérer toute mémoire qui n’est plus utilisée
Utiliser le pointeur après free Comportement indéfini Mettre le pointeur à NULL
Dépasser la taille allouée Écriture hors mémoire Contrôler les indices et la capacité
Affecter directement realloc Perte du pointeur initial en cas d’échec Utiliser un pointeur temporaire
Libérer deux fois le même pointeur Erreur mémoire grave Mettre le pointeur à NULL après libération
malloc, calloc et realloc — Tableau comparatif
Fonction Utilisation Initialisation
malloc Créer une nouvelle zone mémoire Contenu non initialisé
calloc Créer un tableau de plusieurs éléments Mémoire initialisée à zéro
realloc Agrandir ou réduire une zone existante Les nouvelles cases ne sont pas initialisées
free Libérer la mémoire allouée Le pointeur ne doit plus être utilisé

Fonctions qui Retournent des Tableaux en C

Les tableaux en langage C : méthodes, exemples et exercices corrigés

Voici une série d’exercices corrigés sur les tableaux en langage C, allant des bases aux concepts plus avancés. Ces exercices vous aideront à mieux comprendre la manipulation des tableaux et les opérations associées.

Exercice 1 : Remplir un tableau et afficher ses éléments

Énoncé :

Écrivez un programme en C qui remplit un tableau de 5 entiers donnés par l’utilisateur et affiche ensuite les éléments du tableau.

Correction :

#include <stdio.h>

int main() {
    int tableau[5];

    // Saisie des éléments du tableau
    for(int i = 0; i < 5; i++) {
        printf("Entrez l'élément %d : ", i + 1);
        scanf("%d", &tableau[i]);
    }

    // Affichage des éléments du tableau
    printf("Les éléments du tableau sont :\n");
    for(int i = 0; i < 5; i++) {
        printf("%d ", tableau[i]);
    }
    printf("\n");

    return 0;
}

Explication :

  • Le tableau tableau[5] est utilisé pour stocker 5 entiers.
  • Une boucle for remplit le tableau avec les entrées de l’utilisateur.
  • Une deuxième boucle for affiche les éléments du tableau.

Exercice 2 : Trouver la valeur maximale d’un tableau

Énoncé :

Écrivez un programme en C qui demande à l’utilisateur de remplir un tableau de 10 entiers, puis trouve et affiche la valeur maximale dans ce tableau.

Correction :

#include <stdio.h>

int main() {
    int tableau[10];
    int max;

    // Saisie des éléments du tableau
    for (int i = 0; i < 10; i++) {
        printf("Entrez l'élément %d : ", i + 1);
        scanf("%d", &tableau[i]);
    }

    // Initialisation de la variable max avec le premier élément du tableau
    max = tableau[0];

    // Recherche du maximum
    for (int i = 1; i < 10; i++) {
        if (tableau[i] > max) {
            max = tableau[i];
        }
    }

    // Affichage du maximum
    printf("La valeur maximale est : %d\n", max);

    return 0;
}

Explication :

  • Le programme initialise la variable max avec le premier élément du tableau.
  • Ensuite, une boucle parcourt les autres éléments du tableau pour trouver le plus grand élément.

Exercice 3 : Calcul de la moyenne d’un tableau

Énoncé :

Écrivez un programme en C qui lit 5 nombres flottants, les stocke dans un tableau, et affiche ensuite la moyenne de ces nombres.

Correction :

#include <stdio.h>

int main() {
    float tableau[5], somme = 0.0, moyenne;

    // Saisie des éléments du tableau
    for(int i = 0; i < 5; i++) {
        printf("Entrez l'élément %d : ", i + 1);
        scanf("%f", &tableau[i]);
        somme += tableau[i];  // Ajouter chaque élément à la somme
    }

    // Calcul de la moyenne
    moyenne = somme / 5;

    // Affichage de la moyenne
    printf("La moyenne des éléments est : %.2f\n", moyenne);

    return 0;
}

Explication :

  • Le tableau tableau[5] contient des nombres flottants.
  • À chaque itération, les éléments sont ajoutés à la somme, et à la fin, la moyenne est calculée en divisant la somme par 5.

Exercice 4 : Inverser les éléments d’un tableau

Énoncé :

Écrivez un programme en C qui lit 6 entiers, les stocke dans un tableau, puis affiche les éléments dans l’ordre inverse.

Correction :

#include <stdio.h>

int main() {
    int tableau[6];

    // Saisie des éléments du tableau
    for(int i = 0; i < 6; i++) {
        printf("Entrez l'élément %d : ", i + 1);
        scanf("%d", &tableau[i]);
    }

    // Affichage des éléments dans l'ordre inverse
    printf("Les éléments du tableau dans l'ordre inverse sont :\n");
    for(int i = 5; i >= 0; i--) {
        printf("%d ", tableau[i]);
    }
    printf("\n");

    return 0;
}

Explication :

  • Le programme lit 6 entiers dans un tableau.
  • Ensuite, une boucle for inverse les éléments en commençant par le dernier et en affichant chaque élément.

Exercice 5 : Tri d’un tableau (Tri par sélection)

Énoncé :

Écrivez un programme en C qui lit 5 entiers, les stocke dans un tableau, puis les trie dans l’ordre croissant en utilisant l’algorithme du tri par sélection.

Correction :

#include <stdio.h>

int main() {
    int tableau[5], i, j, min, temp;

    // Saisie des éléments du tableau
    for(i = 0; i < 5; i++) {
        printf("Entrez l'élément %d : ", i + 1);
        scanf("%d", &tableau[i]);
    }

    // Tri par sélection
    for(i = 0; i < 4; i++) {
        min = i;
        for(j = i + 1; j < 5; j++) {
            if(tableau[j] < tableau[min]) {
                min = j;
            }
        }
        // Échange des éléments
        temp = tableau[min];
        tableau[min] = tableau[i];
        tableau[i] = temp;
    }

    // Affichage du tableau trié
    printf("Le tableau trié est :\n");
    for(i = 0; i < 5; i++) {
        printf("%d ", tableau[i]);
    }
    printf("\n");

    return 0;
}

Explication :

  • Le programme utilise l’algorithme du tri par sélection pour trier un tableau de 5 entiers.
  • À chaque itération, il trouve l’élément minimum dans la partie non triée du tableau et le place à la position correcte en l’échangeant avec l’élément actuel.

Exercice 6 : Fusionner deux tableaux

Énoncé :

Écrivez un programme en C qui lit deux tableaux de 5 entiers chacun, puis les fusionne dans un troisième tableau.

Correction :

#include <stdio.h>

int main() {
    int tableau1[5], tableau2[5], tableau_fusion[10];

    // Saisie des éléments du premier tableau
    printf("Entrez les éléments du premier tableau :\n");
    for(int i = 0; i < 5; i++) {
        scanf("%d", &tableau1[i]);
    }

    // Saisie des éléments du deuxième tableau
    printf("Entrez les éléments du deuxième tableau :\n");
    for(int i = 0; i < 5; i++) {
        scanf("%d", &tableau2[i]);
    }

    // Fusion des deux tableaux
    for(int i = 0; i < 5; i++) {
        tableau_fusion[i] = tableau1[i];
        tableau_fusion[i + 5] = tableau2[i];
    }

    // Affichage du tableau fusionné
    printf("Le tableau fusionné est :\n");
    for(int i = 0; i < 10; i++) {
        printf("%d ", tableau_fusion[i]);
    }
    printf("\n");

    return 0;
}

Explication :

  • Le programme fusionne les éléments des deux tableaux de 5 entiers dans un troisième tableau de 10 entiers.
  • Le premier tableau est copié dans la première moitié du tableau fusionné, et le deuxième tableau est copié dans la deuxième moitié.

Ces exercices tableaux en langage C vous permettent de pratiquer les bases et des concepts légèrement plus avancés liés aux tableaux en C. Vous pouvez essayer d’autres variantes, comme implémenter des algorithmes de tri plus complexes ou travailler sur des tableaux dynamiques.

📊 Tableau à deux dimensions en C : Guide complet + 8 exercices corrigés

Les tableaux à deux dimensions en langage C, également appelés tableaux bidimensionnels ou matrices, permettent de stocker des données organisées sous forme de lignes et de colonnes. Ils sont utilisés dans de nombreux domaines : calcul scientifique, traitement d’images, intelligence artificielle, statistiques, jeux vidéo, finance, robotique et programmation embarquée.

Maîtriser les matrices en C constitue une étape essentielle avant d’aborder les structures de données plus avancées comme les pointeurs, les tableaux dynamiques ou les algorithmes matriciels.

Déclaration d’un tableau bidimensionnel

int notes[4][3];

Ce tableau contient :

  • ✔ 4 lignes
  • ✔ 3 colonnes
  • ✔ 12 cases mémoire

Initialisation

int matrice[3][3]={
 {1,2,3},
 {4,5,6},
 {7,8,9}
};

Parcourir une matrice

for(i=0;i<3;i++)
{
    for(j=0;j<3;j++)
    {
        printf("%d ",matrice[i][j]);
    }
    printf("\n");
}

Applications concrètes

  • 📈 Tableaux de notes
  • 📦 Gestion de stock
  • 🌡 Températures de capteurs
  • 🧮 Calcul matriciel
  • 📷 Traitement d’images (pixels)
  • 🤖 Intelligence artificielle
  • 🎮 Cartes de jeux vidéo
  • 📊 Analyse statistique

📝 8 Exercices corrigés sur les tableaux bidimensionnels

Exercice Objectif Difficulté
1. Afficher une matrice Parcourir lignes et colonnes
2. Calculer la somme des éléments Boucles imbriquées
3. Moyenne d’une ligne Calcul statistique ⭐⭐
4. Addition de deux matrices Double parcours ⭐⭐
5. Transposer une matrice Échanger lignes et colonnes ⭐⭐⭐
6. Rechercher une valeur Recherche séquentielle ⭐⭐⭐
7. Calcul de la diagonale principale Indices identiques ⭐⭐⭐
8. Multiplication de matrices Trois boucles imbriquées ⭐⭐⭐⭐

Compétences acquises

  • ✔ Déclarer une matrice en C
  • ✔ Initialiser un tableau bidimensionnel
  • ✔ Parcourir lignes et colonnes
  • ✔ Manipuler plusieurs matrices
  • ✔ Effectuer des calculs matriciels
  • ✔ Rechercher une valeur
  • ✔ Calculer une diagonale
  • ✔ Réaliser une transposition
  • ✔ Préparer les algorithmes de traitement d’images et de calcul scientifique

🎯 Cette section répond aux recherches suivantes

  • ✅ tableau 2d c
  • ✅ matrice c
  • ✅ tableau bidimensionnel c
  • ✅ exercices matrice c
  • ✅ exercices tableau 2 dimensions c corrigés
  • ✅ manipulation de matrices en langage C
  • ✅ tableau multidimensionnel C
  • ✅ cours tableau bidimensionnel C PDF

🧠 Les tableaux et les pointeurs en langage C

En langage C, les tableaux et les pointeurs sont étroitement liés. Le nom d’un tableau représente généralement l’adresse de son premier élément. Cette relation permet de parcourir, transmettre et modifier un tableau à l’aide de l’arithmétique des pointeurs.

Principe essentiel :
Pour un tableau nommé tab, les expressions tab[i] et *(tab + i) désignent la même valeur.

1. Le nom du tableau représente une adresse

Considérons un tableau de cinq entiers :

int tab[5] = {10, 20, 30, 40, 50};

Dans la plupart des expressions, tab correspond à l’adresse du premier élément du tableau, c’est-à-dire à &tab[0].

Expression Signification
tab Adresse du premier élément
&tab[0] Adresse du premier élément
*tab Valeur du premier élément
tab + 2 Adresse du troisième élément
*(tab + 2) Valeur du troisième élément

2. Comprendre l’équivalence entre tab[i] et *(tab + i)

printf("%d\n", tab[2]);
printf("%d\n", *(tab + 2));

Les deux instructions affichent 30. L’indice 2 indique que le programme doit avancer de deux éléments depuis l’adresse de départ du tableau.

tab[0]
10
tab[1]
20
tab[2]
30
tab[3]
40
tab[4]
50

3. Parcourir un tableau avec un pointeur

Un pointeur peut recevoir l’adresse du premier élément du tableau, puis avancer case par case.

#include <stdio.h>

int main(void)
{
    int tab[5] = {10, 20, 30, 40, 50};
    int *p = tab;

    for (int i = 0; i < 5; i++)
    {
        printf("%d ", *(p + i));
    }

    return 0;
}

Le pointeur p contient l’adresse du premier élément. L’expression p + i désigne l’adresse de l’élément situé à l’indice i.

4. Modifier les valeurs avec un pointeur

int tab[4] = {2, 4, 6, 8};
int *p = tab;

for (int i = 0; i < 4; i++)
{
    *(p + i) = *(p + i) * 2;
}

Après l’exécution, le tableau contient : 4, 8, 12 et 16. Le pointeur permet donc de lire mais aussi de modifier directement les cases du tableau.

5. Passer un tableau à une fonction

Lorsqu’un tableau est transmis à une fonction, celle-ci reçoit en réalité l’adresse de son premier élément.

#include <stdio.h>

void afficherTableau(const int *tab, int taille)
{
    for (int i = 0; i < taille; i++)
    {
        printf("%d ", tab[i]);
    }
}

int main(void)
{
    int valeurs[5] = {3, 6, 9, 12, 15};

    afficherTableau(valeurs, 5);

    return 0;
}

Les écritures suivantes sont équivalentes dans les paramètres d’une fonction :

void afficher(int tab[], int taille);
void afficher(int *tab, int taille);

6. Calculer la somme d’un tableau avec un pointeur

#include <stdio.h>

int sommeTableau(const int *tab, int taille)
{
    int somme = 0;

    for (int i = 0; i < taille; i++)
    {
        somme += *(tab + i);
    }

    return somme;
}

int main(void)
{
    int nombres[5] = {5, 10, 15, 20, 25};

    printf("Somme : %d", sommeTableau(nombres, 5));

    return 0;
}

Le programme affiche : Somme : 75.

7. Tableau fixe et pointeur : quelles différences ?

Caractéristique Tableau Pointeur
Stockage Réserve un bloc de mémoire Stocke une adresse
Réaffectation Le nom du tableau ne peut pas changer d’adresse Le pointeur peut recevoir une autre adresse
sizeof Retourne la taille totale du tableau Retourne la taille du pointeur
Accès tab[i] *(p + i)

8. Attention à sizeof dans une fonction

Dans la fonction principale, il est possible de calculer le nombre d’éléments d’un tableau avec :

int taille = sizeof(tab) / sizeof(tab[0]);

Cette méthode ne fonctionne plus après le passage du tableau à une fonction, car le paramètre est alors traité comme un pointeur. Il faut transmettre explicitement la taille du tableau.

Erreur fréquente :
croire qu’une fonction peut déterminer automatiquement la longueur d’un tableau reçu avec sizeof.

9. Erreurs fréquentes avec les tableaux et les pointeurs

  • Accéder à un indice situé en dehors du tableau.
  • Déréférencer un pointeur non initialisé.
  • Confondre l’adresse d’une case et sa valeur.
  • Utiliser sizeof sur un paramètre de fonction.
  • Modifier un tableau déclaré avec des données constantes.
  • Oublier de transmettre la taille du tableau.
  • Déplacer un pointeur au-delà de la zone mémoire autorisée.

10. Mini-exercice corrigé

Écrire un programme qui recherche la plus grande valeur d’un tableau en utilisant uniquement un pointeur.

#include <stdio.h>

int maximum(const int *tab, int taille)
{
    int max = *tab;

    for (int i = 1; i < taille; i++)
    {
        if (*(tab + i) > max)
        {
            max = *(tab + i);
        }
    }

    return max;
}

int main(void)
{
    int tab[6] = {14, 7, 32, 18, 45, 11};

    printf("Maximum : %d", maximum(tab, 6));

    return 0;
}

Résultat obtenu : Maximum : 45.

🎯 Notions maîtrisées après cette section

  • Comprendre le lien entre tableau et adresse mémoire.
  • Utiliser l’équivalence entre tab[i] et *(tab + i).
  • Parcourir un tableau avec un pointeur.
  • Modifier les valeurs d’un tableau par adresse.
  • Passer un tableau à une fonction.
  • Éviter les erreurs liées à sizeof.
  • Préparer l’apprentissage de malloc, calloc et realloc.
💾 Allocation dynamique en langage C : malloc, calloc, realloc et free

L’allocation dynamique en langage C permet de réserver de la mémoire pendant l’exécution du programme. Contrairement à un tableau fixe, dont la taille est déterminée à la compilation, un tableau dynamique peut être créé selon une valeur saisie par l’utilisateur ou calculée par le programme.

Cette technique repose principalement sur les fonctions malloc(), calloc(), realloc() et free(), disponibles dans la bibliothèque <stdlib.h>.

Principe essentiel :
toute zone mémoire réservée dynamiquement doit être libérée avec free() lorsqu’elle devient inutile.

1. Pourquoi utiliser un tableau dynamique ?

Un tableau classique possède une taille fixe :

int tab[100];

Ce tableau réserve toujours la mémoire nécessaire pour 100 entiers, même si le programme n’en utilise que 10. À l’inverse, l’allocation dynamique permet d’adapter la taille du tableau au besoin réel.

Tableau fixe Tableau dynamique
Taille souvent connue à l’avance Taille définie pendant l’exécution
Mémoire réservée automatiquement Mémoire réservée manuellement
Taille difficile à modifier Taille modifiable avec realloc()
Pas de free() free() obligatoire

2. Réserver un tableau avec malloc()

La fonction malloc() réserve un nombre d’octets donné et retourne l’adresse du premier octet réservé.

int *tab = malloc(taille * sizeof(int));

L’expression taille * sizeof(int) calcule la quantité de mémoire nécessaire pour stocker le nombre demandé d’entiers.

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int taille;

    printf("Nombre d'elements : ");
    scanf("%d", &taille);

    int *tab = malloc(taille * sizeof(int));

    if (tab == NULL)
    {
        printf("Erreur d'allocation memoire.\n");
        return 1;
    }

    for (int i = 0; i < taille; i++)
    {
        printf("tab[%d] = ", i);
        scanf("%d", &tab[i]);
    }

    for (int i = 0; i < taille; i++)
    {
        printf("%d ", tab[i]);
    }

    free(tab);
    tab = NULL;

    return 0;
}
Vérification indispensable :
si malloc() ne parvient pas à réserver la mémoire demandée, elle retourne NULL. Le programme doit tester ce résultat avant d’utiliser le pointeur.

3. Initialiser la mémoire avec calloc()

La fonction calloc() réserve une zone mémoire et initialise tous ses octets à zéro. Elle reçoit deux arguments : le nombre d’éléments et la taille d’un élément.

int *tab = calloc(taille, sizeof(int));

Pour un tableau d’entiers, les cases sont ainsi initialisées à zéro avant leur première utilisation.

Fonction Réservation Initialisation
malloc() Oui Valeurs indéterminées
calloc() Oui Octets initialisés à zéro

4. Agrandir ou réduire un tableau avec realloc()

La fonction realloc() modifie la taille d’une zone mémoire déjà réservée. Elle peut conserver la même adresse ou déplacer les données vers une nouvelle zone.

int *temp = realloc(tab, nouvelleTaille * sizeof(int));

Il est préférable d’utiliser un pointeur temporaire. En cas d’échec, realloc() retourne NULL, mais l’ancienne zone mémoire reste encore valide.

int *temp = realloc(tab, nouvelleTaille * sizeof(int));

if (temp == NULL)
{
    printf("Impossible de redimensionner le tableau.\n");
    free(tab);
    return 1;
}

tab = temp;

5. Libérer la mémoire avec free()

La fonction free() restitue au système une zone réservée avec malloc(), calloc() ou realloc().

free(tab);
tab = NULL;

L’affectation de NULL après free() permet d’éviter de conserver un pointeur vers une zone mémoire qui n’est plus accessible.

6. Exemple complet : moyenne d’un tableau dynamique

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int taille;
    double somme = 0.0;

    printf("Combien de notes souhaitez-vous saisir ? ");
    scanf("%d", &taille);

    if (taille <= 0)
    {
        printf("La taille doit etre positive.\n");
        return 1;
    }

    double *notes = malloc(taille * sizeof(double));

    if (notes == NULL)
    {
        printf("Erreur d'allocation memoire.\n");
        return 1;
    }

    for (int i = 0; i < taille; i++)
    {
        printf("Note %d : ", i + 1);
        scanf("%lf", &notes[i]);
        somme += notes[i];
    }

    printf("Moyenne : %.2f\n", somme / taille);

    free(notes);
    notes = NULL;

    return 0;
}

7. Créer une matrice dynamique

Une matrice dynamique peut être représentée par un tableau de pointeurs. Chaque pointeur correspond à une ligne.

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int lignes = 3;
    int colonnes = 4;

    int **matrice = malloc(lignes * sizeof(int *));

    if (matrice == NULL)
    {
        return 1;
    }

    for (int i = 0; i < lignes; i++)
    {
        matrice[i] = malloc(colonnes * sizeof(int));

        if (matrice[i] == NULL)
        {
            for (int k = 0; k < i; k++)
            {
                free(matrice[k]);
            }

            free(matrice);
            return 1;
        }
    }

    for (int i = 0; i < lignes; i++)
    {
        for (int j = 0; j < colonnes; j++)
        {
            matrice[i][j] = i + j;
        }
    }

    for (int i = 0; i < lignes; i++)
    {
        free(matrice[i]);
    }

    free(matrice);
    matrice = NULL;

    return 0;
}
Ordre de libération :
pour une matrice dynamique, il faut d’abord libérer chaque ligne, puis libérer le tableau contenant les pointeurs vers ces lignes.

8. Erreurs fréquentes en allocation dynamique

  • Utiliser un pointeur sans vérifier s’il vaut NULL.
  • Oublier d’inclure <stdlib.h>.
  • Réserver un nombre d’octets insuffisant.
  • Oublier d’appeler free().
  • Utiliser un pointeur après sa libération.
  • Libérer deux fois la même zone mémoire.
  • Écraser le pointeur original directement avec realloc().
  • Accéder à une case située au-delà de la taille réservée.

9. Mini-exercice corrigé : agrandir un tableau

Le programme suivant crée un tableau de trois entiers, puis l’agrandit pour ajouter deux nouvelles valeurs.

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int taille = 3;
    int *tab = malloc(taille * sizeof(int));

    if (tab == NULL)
    {
        return 1;
    }

    tab[0] = 10;
    tab[1] = 20;
    tab[2] = 30;

    int nouvelleTaille = 5;
    int *temp = realloc(tab, nouvelleTaille * sizeof(int));

    if (temp == NULL)
    {
        free(tab);
        return 1;
    }

    tab = temp;
    tab[3] = 40;
    tab[4] = 50;

    for (int i = 0; i < nouvelleTaille; i++)
    {
        printf("%d ", tab[i]);
    }

    free(tab);
    tab = NULL;

    return 0;
}

Résultat : 10 20 30 40 50

🎯 Compétences acquises

  • Créer un tableau dynamique avec malloc().
  • Initialiser une zone mémoire avec calloc().
  • Redimensionner un tableau avec realloc().
  • Libérer correctement une zone avec free().
  • Détecter un échec d’allocation.
  • Manipuler un tableau dont la taille est saisie par l’utilisateur.
  • Créer et libérer une matrice dynamique.
  • Éviter les fuites mémoire et les pointeurs invalides.
🔤 Les chaînes de caractères en langage C

En langage C, une chaîne de caractères est représentée par un tableau de variables de type char. Chaque case contient un caractère et la chaîne se termine obligatoirement par le caractère spécial '\0', appelé caractère nul.

La maîtrise des chaînes de caractères permet de traiter des noms, des phrases, des mots de passe, des fichiers texte, des commandes utilisateur et de nombreuses données saisies au clavier.

Principe essentiel :
une chaîne en C est un tableau de caractères terminé par '\0'. Sans ce caractère, les fonctions de traitement ne peuvent pas déterminer où la chaîne se termine.

1. Déclarer une chaîne de caractères

Une chaîne peut être déclarée comme un tableau de caractères :

char nom[20];

Ce tableau peut contenir jusqu’à 19 caractères utiles. La dernière case doit rester disponible pour le caractère nul '\0'.

2. Initialiser une chaîne

char ville[] = "Paris";

Le compilateur crée automatiquement le tableau suivant :

P
0
a
1
r
2
i
3
s
4
\0
5

Les deux déclarations suivantes produisent le même résultat :

char ville[] = "Paris";

char ville[] = {'P', 'a', 'r', 'i', 's', '\0'};

3. Afficher une chaîne avec printf()

#include <stdio.h>

int main(void)
{
    char langage[] = "Langage C";

    printf("%s\n", langage);

    return 0;
}

Le spécificateur %s permet d’afficher les caractères jusqu’à la rencontre de '\0'.

4. Lire une chaîne saisie par l’utilisateur

La fonction scanf() peut lire un mot simple :

char prenom[30];

printf("Prenom : ");
scanf("%29s", prenom);

La limite 29 protège le tableau contre un dépassement de capacité. Cependant, scanf("%s") s’arrête au premier espace.

Exemple :
si l’utilisateur saisit Jean Dupont, seul le mot Jean sera enregistré avec scanf("%s").

5. Lire une phrase avec fgets()

La fonction fgets() est mieux adaptée pour lire une phrase contenant des espaces.

#include <stdio.h>

int main(void)
{
    char phrase[100];

    printf("Saisissez une phrase : ");
    fgets(phrase, sizeof(phrase), stdin);

    printf("Phrase : %s", phrase);

    return 0;
}

fgets() limite automatiquement le nombre de caractères lus selon la taille du tableau. Elle peut toutefois conserver le caractère de retour à la ligne '\n'.

6. Supprimer le retour à la ligne de fgets()

#include <stdio.h>
#include <string.h>

int main(void)
{
    char nom[50];

    printf("Nom complet : ");
    fgets(nom, sizeof(nom), stdin);

    nom[strcspn(nom, "\n")] = '\0';

    printf("Bonjour %s\n", nom);

    return 0;
}

La fonction strcspn() repère la position du premier retour à la ligne. Celui-ci est ensuite remplacé par '\0'.

7. Les fonctions principales de string.h

La bibliothèque <string.h> fournit plusieurs fonctions pour manipuler les chaînes.

Fonction Rôle Exemple
strlen() Calculer la longueur strlen(texte)
strcpy() Copier une chaîne strcpy(copie, source)
strcat() Concaténer deux chaînes strcat(texte, suite)
strcmp() Comparer deux chaînes strcmp(a, b)
strchr() Chercher un caractère strchr(texte, 'a')
strstr() Chercher une sous-chaîne strstr(texte, "C")

8. Calculer la longueur avec strlen()

#include <stdio.h>
#include <string.h>

int main(void)
{
    char mot[] = "programmation";

    printf("Longueur : %zu\n", strlen(mot));

    return 0;
}

strlen() compte les caractères situés avant '\0'. Le caractère nul ne fait donc pas partie de la longueur retournée.

9. Copier une chaîne avec strcpy()

#include <stdio.h>
#include <string.h>

int main(void)
{
    char source[] = "Tableau";
    char copie[20];

    strcpy(copie, source);

    printf("%s\n", copie);

    return 0;
}

Le tableau de destination doit être suffisamment grand pour recevoir la chaîne source ainsi que le caractère nul final.

10. Concaténer avec strcat()

#include <stdio.h>
#include <string.h>

int main(void)
{
    char phrase[50] = "Langage";
    char suite[] = " C";

    strcat(phrase, suite);

    printf("%s\n", phrase);

    return 0;
}

Le résultat est Langage C. La chaîne de destination doit disposer d’un espace suffisant pour contenir les deux chaînes réunies.

11. Comparer deux chaînes avec strcmp()

L’opérateur == ne compare pas le contenu de deux chaînes. Il compare leurs adresses. Pour comparer leur texte, il faut utiliser strcmp().

#include <stdio.h>
#include <string.h>

int main(void)
{
    char mot1[] = "code";
    char mot2[] = "code";

    if (strcmp(mot1, mot2) == 0)
    {
        printf("Les chaines sont identiques.\n");
    }

    return 0;
}
Résultat de strcmp() Interprétation
0 Les chaînes sont identiques
Valeur négative La première chaîne précède la seconde
Valeur positive La première chaîne suit la seconde

12. Parcourir une chaîne caractère par caractère

#include <stdio.h>

int main(void)
{
    char mot[] = "ordinateur";

    for (int i = 0; mot[i] != '\0'; i++)
    {
        printf("%c\n", mot[i]);
    }

    return 0;
}

La boucle continue tant que le caractère rencontré est différent de '\0'.

13. Compter les voyelles d’une chaîne

#include <stdio.h>

int main(void)
{
    char texte[] = "programmation";
    int voyelles = 0;

    for (int i = 0; texte[i] != '\0'; i++)
    {
        char c = texte[i];

        if (c == 'a' || c == 'e' || c == 'i' ||
            c == 'o' || c == 'u' || c == 'y')
        {
            voyelles++;
        }
    }

    printf("Nombre de voyelles : %d\n", voyelles);

    return 0;
}

14. Convertir une chaîne en majuscules

#include <stdio.h>
#include <ctype.h>

int main(void)
{
    char texte[] = "langage c";

    for (int i = 0; texte[i] != '\0'; i++)
    {
        texte[i] = (char)toupper((unsigned char)texte[i]);
    }

    printf("%s\n", texte);

    return 0;
}

La fonction toupper(), disponible dans <ctype.h>, convertit une lettre minuscule en majuscule.

15. Inverser une chaîne sans fonction spécialisée

#include <stdio.h>
#include <string.h>

int main(void)
{
    char mot[] = "tableau";
    int gauche = 0;
    int droite = (int)strlen(mot) - 1;

    while (gauche < droite)
    {
        char temp = mot[gauche];
        mot[gauche] = mot[droite];
        mot[droite] = temp;

        gauche++;
        droite--;
    }

    printf("%s\n", mot);

    return 0;
}

Le programme affiche uaelbat.

16. Tableau de chaînes de caractères

Un tableau à deux dimensions peut stocker plusieurs chaînes de même capacité maximale.

#include <stdio.h>

int main(void)
{
    char villes[4][20] = {
        "Paris",
        "Lyon",
        "Marseille",
        "Toulouse"
    };

    for (int i = 0; i < 4; i++)
    {
        printf("%s\n", villes[i]);
    }

    return 0;
}

Le tableau contient quatre lignes. Chaque ligne peut stocker une chaîne de 19 caractères maximum, plus le caractère nul.

17. Tableau de pointeurs vers des chaînes

#include <stdio.h>

int main(void)
{
    const char *villes[] = {
        "Paris",
        "Lyon",
        "Marseille",
        "Toulouse"
    };

    int nombre = sizeof(villes) / sizeof(villes[0]);

    for (int i = 0; i < nombre; i++)
    {
        printf("%s\n", villes[i]);
    }

    return 0;
}

Chaque case du tableau contient ici un pointeur vers le premier caractère d’une chaîne. Le mot-clé const évite de modifier les littéraux de chaîne.

18. Erreurs fréquentes avec les chaînes

  • Oublier la place nécessaire pour '\0'.
  • Utiliser gets(), une fonction dangereuse supprimée du standard moderne.
  • Lire trop de caractères dans un tableau trop petit.
  • Comparer deux chaînes avec ==.
  • Utiliser strcpy() sans vérifier la capacité de destination.
  • Concaténer des chaînes sans réserver assez de mémoire.
  • Modifier directement un littéral de chaîne.
  • Confondre strlen() avec sizeof().
  • Oublier de retirer le retour à la ligne conservé par fgets().

19. Différence entre strlen() et sizeof()

#include <stdio.h>
#include <string.h>

int main(void)
{
    char mot[] = "chat";

    printf("strlen : %zu\n", strlen(mot));
    printf("sizeof : %zu\n", sizeof(mot));

    return 0;
}

strlen(mot) retourne 4, car elle compte les lettres. sizeof(mot) retourne 5, car elle inclut également le caractère nul final.

20. Mini-exercice corrigé : détecter un palindrome

Un palindrome est un mot qui se lit de la même manière dans les deux sens, comme radar.

#include <stdio.h>
#include <string.h>

int main(void)
{
    char mot[50];
    int palindrome = 1;

    printf("Saisissez un mot : ");
    scanf("%49s", mot);

    int longueur = (int)strlen(mot);

    for (int i = 0; i < longueur / 2; i++)
    {
        if (mot[i] != mot[longueur - 1 - i])
        {
            palindrome = 0;
            break;
        }
    }

    if (palindrome)
    {
        printf("Le mot est un palindrome.\n");
    }
    else
    {
        printf("Le mot n'est pas un palindrome.\n");
    }

    return 0;
}

🎯 Compétences acquises

  • Déclarer et initialiser une chaîne en langage C.
  • Comprendre le rôle du caractère '\0'.
  • Lire un mot avec scanf().
  • Lire une phrase avec fgets().
  • Utiliser strlen(), strcpy(), strcat() et strcmp().
  • Parcourir et transformer les caractères d’une chaîne.
  • Créer un tableau de chaînes.
  • Comparer, inverser et analyser un texte.
  • Éviter les dépassements de mémoire liés aux chaînes.
⚙️ Les algorithmes classiques sur les tableaux en langage C

Les algorithmes sur tableaux en langage C permettent de rechercher, classer, compter, comparer ou transformer une série de valeurs. Ils constituent une base essentielle de l’algorithmique et préparent à l’étude des pointeurs, des structures de données, de la complexité et de l’optimisation des programmes.

Objectif :
maîtriser les opérations classiques sur un tableau : recherche, tri, minimum, maximum, inversion, fusion, suppression des doublons et comparaison des performances.

1. Rechercher une valeur dans un tableau

La recherche séquentielle parcourt le tableau case par case jusqu’à trouver la valeur recherchée.

#include <stdio.h>

int rechercher(const int tab[], int taille, int valeur)
{
    for (int i = 0; i < taille; i++)
    {
        if (tab[i] == valeur)
        {
            return i;
        }
    }

    return -1;
}

int main(void)
{
    int tab[] = {12, 7, 25, 18, 9};
    int taille = sizeof(tab) / sizeof(tab[0]);
    int position = rechercher(tab, taille, 18);

    if (position != -1)
    {
        printf("Valeur trouvee a l'indice %d\n", position);
    }
    else
    {
        printf("Valeur absente\n");
    }

    return 0;
}

Dans le pire des cas, le programme examine toutes les cases du tableau. Sa complexité est donc O(n).

2. Recherche dichotomique

La recherche dichotomique fonctionne uniquement sur un tableau déjà trié. Elle divise la zone de recherche par deux à chaque étape.

int rechercheDichotomique(const int tab[], int taille, int valeur)
{
    int gauche = 0;
    int droite = taille - 1;

    while (gauche <= droite)
    {
        int milieu = gauche + (droite - gauche) / 2;

        if (tab[milieu] == valeur)
        {
            return milieu;
        }

        if (tab[milieu] < valeur)
        {
            gauche = milieu + 1;
        }
        else
        {
            droite = milieu - 1;
        }
    }

    return -1;
}

Sa complexité est O(log n), ce qui la rend nettement plus rapide sur les grands tableaux triés.

Méthode Condition Complexité
Recherche séquentielle Tableau trié ou non O(n)
Recherche dichotomique Tableau obligatoirement trié O(log n)

3. Trouver le minimum et le maximum

int minimum(const int tab[], int taille)
{
    int min = tab[0];

    for (int i = 1; i < taille; i++)
    {
        if (tab[i] < min)
        {
            min = tab[i];
        }
    }

    return min;
}

int maximum(const int tab[], int taille)
{
    int max = tab[0];

    for (int i = 1; i < taille; i++)
    {
        if (tab[i] > max)
        {
            max = tab[i];
        }
    }

    return max;
}

4. Inverser un tableau

L’inversion échange la première valeur avec la dernière, la deuxième avec l’avant-dernière, puis continue jusqu’au centre.

void inverser(int tab[], int taille)
{
    int gauche = 0;
    int droite = taille - 1;

    while (gauche < droite)
    {
        int temp = tab[gauche];
        tab[gauche] = tab[droite];
        tab[droite] = temp;

        gauche++;
        droite--;
    }
}

5. Tri à bulles

Le tri à bulles compare les valeurs voisines et les échange lorsqu’elles sont dans le mauvais ordre. Il est simple à comprendre, mais peu performant sur de grands tableaux.

void triBulles(int tab[], int taille)
{
    for (int i = 0; i < taille - 1; i++)
    {
        int echange = 0;

        for (int j = 0; j < taille - 1 - i; j++)
        {
            if (tab[j] > tab[j + 1])
            {
                int temp = tab[j];
                tab[j] = tab[j + 1];
                tab[j + 1] = temp;
                echange = 1;
            }
        }

        if (!echange)
        {
            break;
        }
    }
}

6. Tri par sélection

Le tri par sélection recherche la plus petite valeur dans la partie non triée, puis la place à la position correcte.

void triSelection(int tab[], int taille)
{
    for (int i = 0; i < taille - 1; i++)
    {
        int indiceMin = i;

        for (int j = i + 1; j < taille; j++)
        {
            if (tab[j] < tab[indiceMin])
            {
                indiceMin = j;
            }
        }

        if (indiceMin != i)
        {
            int temp = tab[i];
            tab[i] = tab[indiceMin];
            tab[indiceMin] = temp;
        }
    }
}

7. Tri par insertion

Le tri par insertion construit progressivement une partie triée du tableau. Il est particulièrement efficace sur les petits tableaux ou les tableaux presque triés.

void triInsertion(int tab[], int taille)
{
    for (int i = 1; i < taille; i++)
    {
        int valeur = tab[i];
        int j = i - 1;

        while (j >= 0 && tab[j] > valeur)
        {
            tab[j + 1] = tab[j];
            j--;
        }

        tab[j + 1] = valeur;
    }
}
Algorithme Cas moyen Atout principal
Tri à bulles O(n²) Très pédagogique
Tri par sélection O(n²) Peu d’échanges
Tri par insertion O(n²) Bon sur tableau presque trié

8. Supprimer les doublons d’un tableau trié

int supprimerDoublons(int tab[], int taille)
{
    if (taille == 0)
    {
        return 0;
    }

    int nouvelleTaille = 1;

    for (int i = 1; i < taille; i++)
    {
        if (tab[i] != tab[nouvelleTaille - 1])
        {
            tab[nouvelleTaille] = tab[i];
            nouvelleTaille++;
        }
    }

    return nouvelleTaille;
}

Cette méthode suppose que le tableau est déjà trié. Les valeurs identiques sont alors voisines.

9. Fusionner deux tableaux triés

void fusionner(const int a[], int tailleA,
               const int b[], int tailleB,
               int resultat[])
{
    int i = 0;
    int j = 0;
    int k = 0;

    while (i < tailleA && j < tailleB)
    {
        if (a[i] <= b[j])
        {
            resultat[k++] = a[i++];
        }
        else
        {
            resultat[k++] = b[j++];
        }
    }

    while (i < tailleA)
    {
        resultat[k++] = a[i++];
    }

    while (j < tailleB)
    {
        resultat[k++] = b[j++];
    }
}

10. Compter les occurrences d’une valeur

int compterOccurrences(const int tab[], int taille, int valeur)
{
    int compteur = 0;

    for (int i = 0; i < taille; i++)
    {
        if (tab[i] == valeur)
        {
            compteur++;
        }
    }

    return compteur;
}

11. Décaler les éléments vers la droite

void decalageDroite(int tab[], int taille)
{
    if (taille <= 1)
    {
        return;
    }

    int dernier = tab[taille - 1];

    for (int i = taille - 1; i > 0; i--)
    {
        tab[i] = tab[i - 1];
    }

    tab[0] = dernier;
}

12. Exemple complet : trier puis rechercher

#include <stdio.h>

void triInsertion(int tab[], int taille)
{
    for (int i = 1; i < taille; i++)
    {
        int valeur = tab[i];
        int j = i - 1;

        while (j >= 0 && tab[j] > valeur)
        {
            tab[j + 1] = tab[j];
            j--;
        }

        tab[j + 1] = valeur;
    }
}

int rechercheDichotomique(const int tab[], int taille, int valeur)
{
    int gauche = 0;
    int droite = taille - 1;

    while (gauche <= droite)
    {
        int milieu = gauche + (droite - gauche) / 2;

        if (tab[milieu] == valeur)
        {
            return milieu;
        }

        if (tab[milieu] < valeur)
        {
            gauche = milieu + 1;
        }
        else
        {
            droite = milieu - 1;
        }
    }

    return -1;
}

int main(void)
{
    int tab[] = {34, 12, 7, 45, 19, 28};
    int taille = sizeof(tab) / sizeof(tab[0]);

    triInsertion(tab, taille);

    int position = rechercheDichotomique(tab, taille, 19);

    printf("Position de 19 : %d\n", position);

    return 0;
}

13. Erreurs fréquentes

  • Utiliser une recherche dichotomique sur un tableau non trié.
  • Dépasser la dernière case avec une condition de boucle incorrecte.
  • Oublier de conserver une valeur temporaire lors d’un échange.
  • Confondre indice et valeur.
  • Calculer incorrectement le milieu d’une zone de recherche.
  • Supprimer des doublons sans mettre à jour la taille logique.
  • Comparer des algorithmes sans tenir compte de la taille du tableau.
  • Trier un tableau alors qu’une seule recherche séquentielle suffisait.

14. Exercices d’entraînement

Exercice Compétence Niveau
Rechercher la première occurrence Recherche séquentielle
Trouver le deuxième maximum Comparaison ⭐⭐
Inverser un tableau sans second tableau Échange ⭐⭐
Trier les notes par ordre croissant Tri ⭐⭐⭐
Fusionner deux tableaux triés Fusion ⭐⭐⭐
Comparer les temps de recherche Complexité ⭐⭐⭐⭐

🎯 Compétences acquises

  • Effectuer une recherche séquentielle et dichotomique.
  • Trouver le minimum, le maximum et les occurrences.
  • Inverser, décaler et fusionner des tableaux.
  • Utiliser les tris à bulles, par sélection et par insertion.
  • Supprimer les doublons d’un tableau trié.
  • Comprendre les complexités O(n), O(log n) et O(n²).
  • Choisir un algorithme selon la taille et l’état du tableau.

30 exercices corrigés sur les tableaux en C, classés par niveau

Cette série de 30 exercices sur les tableaux en langage C rassemble les principales notions étudiées : tableaux simples, matrices, chaînes de caractères, pointeurs, allocation dynamique, recherche, tri et algorithmes classiques.

Les exercices sont organisés selon une difficulté progressive. Chaque sujet précise la compétence travaillée, l’objectif attendu et une proposition de correction en langage C.

Niveau 1
8 exercices débutants
Niveau 2
8 exercices intermédiaires
Niveau 3
8 exercices avancés
Niveau 4
6 exercices experts
Conseil d’utilisation :
tentez d’abord de résoudre chaque exercice sans consulter la correction. Testez ensuite votre programme avec plusieurs jeux de données, notamment des tableaux vides, des valeurs négatives, des doublons et des tailles limites.

🔵 Niveau 1 — Exercices débutants

Ce premier niveau porte sur la déclaration, la saisie, l’affichage et les calculs simples dans un tableau à une dimension.

Exercice 1 — Saisir et afficher cinq entiers

Créez un tableau de cinq entiers, demandez à l’utilisateur de saisir les valeurs, puis affichez-les dans le même ordre.

Compétence : déclaration, saisie et parcours d’un tableau.

#include <stdio.h>

int main(void)
{
    int tab[5];

    for (int i = 0; i < 5; i++)
    {
        printf("Valeur %d : ", i + 1);
        scanf("%d", &tab[i]);
    }

    printf("Tableau : ");

    for (int i = 0; i < 5; i++)
    {
        printf("%d ", tab[i]);
    }

    return 0;
}
Exercice 2 — Calculer la somme des éléments

Calculez et affichez la somme de tous les éléments d’un tableau.

Compétence : accumulation dans une boucle.

#include <stdio.h>

int main(void)
{
    int tab[] = {4, 8, 12, 3, 7};
    int taille = sizeof(tab) / sizeof(tab[0]);
    int somme = 0;

    for (int i = 0; i < taille; i++)
    {
        somme += tab[i];
    }

    printf("Somme : %d\n", somme);

    return 0;
}
Exercice 3 — Calculer la moyenne

Calculez la moyenne des valeurs contenues dans un tableau d’entiers.

Compétence : somme, conversion et division.

#include <stdio.h>

int main(void)
{
    int tab[] = {10, 14, 8, 16, 12};
    int taille = sizeof(tab) / sizeof(tab[0]);
    int somme = 0;

    for (int i = 0; i < taille; i++)
    {
        somme += tab[i];
    }

    double moyenne = (double)somme / taille;

    printf("Moyenne : %.2f\n", moyenne);

    return 0;
}
Exercice 4 — Trouver le minimum

Recherchez la plus petite valeur d’un tableau.

Compétence : comparaison et mémorisation d’une valeur.

#include <stdio.h>

int main(void)
{
    int tab[] = {18, 7, 25, 4, 11};
    int taille = sizeof(tab) / sizeof(tab[0]);
    int minimum = tab[0];

    for (int i = 1; i < taille; i++)
    {
        if (tab[i] < minimum)
        {
            minimum = tab[i];
        }
    }

    printf("Minimum : %d\n", minimum);

    return 0;
}
Exercice 5 — Trouver le maximum et son indice

Affichez la plus grande valeur du tableau ainsi que sa position.

Compétence : distinction entre valeur et indice.

#include <stdio.h>

int main(void)
{
    int tab[] = {5, 29, 13, 42, 17};
    int taille = sizeof(tab) / sizeof(tab[0]);
    int indiceMax = 0;

    for (int i = 1; i < taille; i++)
    {
        if (tab[i] > tab[indiceMax])
        {
            indiceMax = i;
        }
    }

    printf("Maximum : %d\n", tab[indiceMax]);
    printf("Indice : %d\n", indiceMax);

    return 0;
}
Exercice 6 — Compter les nombres pairs

Comptez le nombre de valeurs paires présentes dans un tableau.

Compétence : test avec l’opérateur modulo.

#include <stdio.h>

int main(void)
{
    int tab[] = {4, 7, 10, 13, 18, 21};
    int taille = sizeof(tab) / sizeof(tab[0]);
    int compteur = 0;

    for (int i = 0; i < taille; i++)
    {
        if (tab[i] % 2 == 0)
        {
            compteur++;
        }
    }

    printf("Nombres pairs : %d\n", compteur);

    return 0;
}
Exercice 7 — Afficher le tableau à l’envers

Affichez les éléments du dernier au premier sans modifier le tableau.

Compétence : parcours décroissant.

#include <stdio.h>

int main(void)
{
    int tab[] = {2, 4, 6, 8, 10};
    int taille = sizeof(tab) / sizeof(tab[0]);

    for (int i = taille - 1; i >= 0; i--)
    {
        printf("%d ", tab[i]);
    }

    return 0;
}
Exercice 8 — Copier un tableau

Copiez les valeurs d’un premier tableau dans un second tableau de même taille.

Compétence : manipulation simultanée de deux tableaux.

#include <stdio.h>

int main(void)
{
    int source[] = {3, 6, 9, 12, 15};
    int copie[5];
    int taille = sizeof(source) / sizeof(source[0]);

    for (int i = 0; i < taille; i++)
    {
        copie[i] = source[i];
    }

    for (int i = 0; i < taille; i++)
    {
        printf("%d ", copie[i]);
    }

    return 0;
}

🟢 Niveau 2 — Exercices intermédiaires

Ce niveau introduit la recherche, les occurrences, les pointeurs, les chaînes de caractères et les tableaux bidimensionnels.

Exercice 9 — Rechercher une valeur

Demandez une valeur à l’utilisateur et affichez son premier indice dans le tableau. Affichez -1 si elle est absente.

Compétence : recherche séquentielle.

#include <stdio.h>

int main(void)
{
    int tab[] = {8, 14, 3, 21, 14, 9};
    int taille = sizeof(tab) / sizeof(tab[0]);
    int valeur;
    int position = -1;

    printf("Valeur recherchee : ");
    scanf("%d", &valeur);

    for (int i = 0; i < taille; i++)
    {
        if (tab[i] == valeur)
        {
            position = i;
            break;
        }
    }

    printf("Position : %d\n", position);

    return 0;
}
Exercice 10 — Compter les occurrences

Comptez le nombre de fois qu’une valeur apparaît dans le tableau.

Compétence : recherche exhaustive.

#include <stdio.h>

int main(void)
{
    int tab[] = {4, 7, 4, 9, 4, 12};
    int taille = sizeof(tab) / sizeof(tab[0]);
    int valeur = 4;
    int occurrences = 0;

    for (int i = 0; i < taille; i++)
    {
        if (tab[i] == valeur)
        {
            occurrences++;
        }
    }

    printf("Occurrences de %d : %d\n", valeur, occurrences);

    return 0;
}
Exercice 11 — Modifier un tableau avec un pointeur

Multipliez chaque valeur du tableau par deux en utilisant l’écriture *(tab + i).

Compétence : relation entre tableaux et pointeurs.

#include <stdio.h>

int main(void)
{
    int tab[] = {2, 5, 8, 11};
    int taille = sizeof(tab) / sizeof(tab[0]);

    for (int i = 0; i < taille; i++)
    {
        *(tab + i) *= 2;
    }

    for (int i = 0; i < taille; i++)
    {
        printf("%d ", *(tab + i));
    }

    return 0;
}
Exercice 12 — Calculer la longueur d’une chaîne sans strlen()

Comptez les caractères d’une chaîne jusqu’au caractère nul.

Compétence : parcours d’un tableau de caractères.

#include <stdio.h>

int main(void)
{
    char texte[] = "programmation";
    int longueur = 0;

    while (texte[longueur] != '\0')
    {
        longueur++;
    }

    printf("Longueur : %d\n", longueur);

    return 0;
}
Exercice 13 — Compter les voyelles d’une chaîne

Comptez le nombre de voyelles présentes dans un mot ou une phrase.

Compétence : traitement de chaînes.

#include <stdio.h>
#include <ctype.h>

int main(void)
{
    char texte[] = "Langage C";
    int voyelles = 0;

    for (int i = 0; texte[i] != '\0'; i++)
    {
        char c = (char)tolower((unsigned char)texte[i]);

        if (c == 'a' || c == 'e' || c == 'i' ||
            c == 'o' || c == 'u' || c == 'y')
        {
            voyelles++;
        }
    }

    printf("Voyelles : %d\n", voyelles);

    return 0;
}
Exercice 14 — Calculer la somme d’une matrice

Calculez la somme de tous les éléments d’une matrice de trois lignes et trois colonnes.

Compétence : boucles imbriquées.

#include <stdio.h>

int main(void)
{
    int matrice[3][3] = {
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9}
    };

    int somme = 0;

    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            somme += matrice[i][j];
        }
    }

    printf("Somme : %d\n", somme);

    return 0;
}
Exercice 15 — Somme de la diagonale principale

Calculez la somme des éléments situés sur la diagonale principale d’une matrice carrée.

Compétence : exploitation des indices identiques.

#include <stdio.h>

int main(void)
{
    int matrice[3][3] = {
        {2, 4, 6},
        {1, 5, 9},
        {3, 7, 8}
    };

    int somme = 0;

    for (int i = 0; i < 3; i++)
    {
        somme += matrice[i][i];
    }

    printf("Somme diagonale : %d\n", somme);

    return 0;
}
Exercice 16 — Additionner deux matrices

Additionnez deux matrices de même dimension et stockez le résultat dans une troisième matrice.

Compétence : manipulation simultanée de plusieurs matrices.

#include <stdio.h>

int main(void)
{
    int a[2][2] = {
        {1, 2},
        {3, 4}
    };

    int b[2][2] = {
        {5, 6},
        {7, 8}
    };

    int resultat[2][2];

    for (int i = 0; i < 2; i++)
    {
        for (int j = 0; j < 2; j++)
        {
            resultat[i][j] = a[i][j] + b[i][j];
        }
    }

    for (int i = 0; i < 2; i++)
    {
        for (int j = 0; j < 2; j++)
        {
            printf("%d ", resultat[i][j]);
        }

        printf("\n");
    }

    return 0;
}

🟠 Niveau 3 — Exercices avancés

Les exercices avancés combinent tri, transposition, allocation dynamique, fonctions et traitement plus complet des données.

Exercice 17 — Inverser réellement un tableau

Modifiez le tableau afin que ses valeurs soient stockées dans l’ordre inverse.

Compétence : échange de valeurs sans second tableau.

#include <stdio.h>

void inverser(int tab[], int taille)
{
    for (int i = 0; i < taille / 2; i++)
    {
        int temp = tab[i];
        tab[i] = tab[taille - 1 - i];
        tab[taille - 1 - i] = temp;
    }
}

int main(void)
{
    int tab[] = {1, 2, 3, 4, 5, 6};
    int taille = sizeof(tab) / sizeof(tab[0]);

    inverser(tab, taille);

    for (int i = 0; i < taille; i++)
    {
        printf("%d ", tab[i]);
    }

    return 0;
}
Exercice 18 — Trier un tableau par ordre croissant

Triez un tableau avec l’algorithme du tri à bulles.

Compétence : comparaison et échange de valeurs voisines.

#include <stdio.h>

void triBulles(int tab[], int taille)
{
    for (int i = 0; i < taille - 1; i++)
    {
        for (int j = 0; j < taille - 1 - i; j++)
        {
            if (tab[j] > tab[j + 1])
            {
                int temp = tab[j];
                tab[j] = tab[j + 1];
                tab[j + 1] = temp;
            }
        }
    }
}

int main(void)
{
    int tab[] = {14, 3, 27, 8, 19};
    int taille = sizeof(tab) / sizeof(tab[0]);

    triBulles(tab, taille);

    for (int i = 0; i < taille; i++)
    {
        printf("%d ", tab[i]);
    }

    return 0;
}
Exercice 19 — Recherche dichotomique

Recherchez une valeur dans un tableau trié en divisant la zone de recherche par deux.

Compétence : recherche en O(log n).

#include <stdio.h>

int rechercheDichotomique(const int tab[], int taille, int valeur)
{
    int gauche = 0;
    int droite = taille - 1;

    while (gauche <= droite)
    {
        int milieu = gauche + (droite - gauche) / 2;

        if (tab[milieu] == valeur)
        {
            return milieu;
        }

        if (tab[milieu] < valeur)
        {
            gauche = milieu + 1;
        }
        else
        {
            droite = milieu - 1;
        }
    }

    return -1;
}

int main(void)
{
    int tab[] = {2, 5, 8, 12, 18, 25, 31};
    int taille = sizeof(tab) / sizeof(tab[0]);

    printf("Indice : %d\n",
           rechercheDichotomique(tab, taille, 18));

    return 0;
}
Exercice 20 — Transposer une matrice

Transformez les lignes d’une matrice en colonnes.

Compétence : changement d’indices dans une matrice.

#include <stdio.h>

int main(void)
{
    int matrice[2][3] = {
        {1, 2, 3},
        {4, 5, 6}
    };

    int transposee[3][2];

    for (int i = 0; i < 2; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            transposee[j][i] = matrice[i][j];
        }
    }

    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 2; j++)
        {
            printf("%d ", transposee[i][j]);
        }

        printf("\n");
    }

    return 0;
}
Exercice 21 — Créer un tableau dynamique

Demandez la taille du tableau à l’utilisateur, réservez la mémoire avec malloc(), puis calculez la somme des valeurs.

Compétence : allocation dynamique et libération mémoire.

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int taille;
    int somme = 0;

    printf("Taille : ");
    scanf("%d", &taille);

    if (taille <= 0)
    {
        return 1;
    }

    int *tab = malloc((size_t)taille * sizeof(*tab));

    if (tab == NULL)
    {
        return 1;
    }

    for (int i = 0; i < taille; i++)
    {
        scanf("%d", &tab[i]);
        somme += tab[i];
    }

    printf("Somme : %d\n", somme);

    free(tab);
    tab = NULL;

    return 0;
}
Exercice 22 — Agrandir un tableau avec realloc()

Créez un tableau dynamique de trois valeurs, puis agrandissez-le pour ajouter deux éléments.

Compétence : redimensionnement sécurisé d’une zone mémoire.

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int taille = 3;
    int *tab = malloc((size_t)taille * sizeof(*tab));

    if (tab == NULL)
    {
        return 1;
    }

    tab[0] = 10;
    tab[1] = 20;
    tab[2] = 30;

    int nouvelleTaille = 5;
    int *temp = realloc(tab,
                        (size_t)nouvelleTaille * sizeof(*tab));

    if (temp == NULL)
    {
        free(tab);
        return 1;
    }

    tab = temp;
    tab[3] = 40;
    tab[4] = 50;

    for (int i = 0; i < nouvelleTaille; i++)
    {
        printf("%d ", tab[i]);
    }

    free(tab);

    return 0;
}
Exercice 23 — Vérifier si un mot est un palindrome

Vérifiez qu’un mot se lit de la même manière de gauche à droite et de droite à gauche.

Compétence : comparaison symétrique dans une chaîne.

#include <stdio.h>
#include <string.h>

int main(void)
{
    char mot[50];
    int palindrome = 1;

    printf("Mot : ");
    scanf("%49s", mot);

    size_t longueur = strlen(mot);

    for (size_t i = 0; i < longueur / 2; i++)
    {
        if (mot[i] != mot[longueur - 1 - i])
        {
            palindrome = 0;
            break;
        }
    }

    if (palindrome)
    {
        printf("Palindrome\n");
    }
    else
    {
        printf("Pas un palindrome\n");
    }

    return 0;
}
Exercice 24 — Supprimer les doublons d’un tableau trié

Supprimez logiquement les valeurs répétées d’un tableau déjà trié.

Compétence : taille logique et réécriture en place.

#include <stdio.h>

int supprimerDoublons(int tab[], int taille)
{
    if (taille == 0)
    {
        return 0;
    }

    int nouvelleTaille = 1;

    for (int i = 1; i < taille; i++)
    {
        if (tab[i] != tab[nouvelleTaille - 1])
        {
            tab[nouvelleTaille] = tab[i];
            nouvelleTaille++;
        }
    }

    return nouvelleTaille;
}

int main(void)
{
    int tab[] = {1, 1, 2, 2, 2, 4, 5, 5};
    int taille = sizeof(tab) / sizeof(tab[0]);

    taille = supprimerDoublons(tab, taille);

    for (int i = 0; i < taille; i++)
    {
        printf("%d ", tab[i]);
    }

    return 0;
}

🟣 Niveau 4 — Exercices experts

Ces derniers exercices associent plusieurs thèmes et demandent une bonne maîtrise des tableaux, des pointeurs, de la mémoire dynamique et des algorithmes.

Exercice 25 — Fusionner deux tableaux triés

Fusionnez deux tableaux triés dans un troisième tableau, lui aussi trié.

Compétence : parcours synchronisé de deux tableaux.

#include <stdio.h>

void fusionner(const int a[], int tailleA,
               const int b[], int tailleB,
               int resultat[])
{
    int i = 0;
    int j = 0;
    int k = 0;

    while (i < tailleA && j < tailleB)
    {
        if (a[i] <= b[j])
        {
            resultat[k++] = a[i++];
        }
        else
        {
            resultat[k++] = b[j++];
        }
    }

    while (i < tailleA)
    {
        resultat[k++] = a[i++];
    }

    while (j < tailleB)
    {
        resultat[k++] = b[j++];
    }
}

int main(void)
{
    int a[] = {1, 4, 7, 10};
    int b[] = {2, 3, 8, 12, 15};
    int resultat[9];

    fusionner(a, 4, b, 5, resultat);

    for (int i = 0; i < 9; i++)
    {
        printf("%d ", resultat[i]);
    }

    return 0;
}
Exercice 26 — Multiplier deux matrices

Multipliez une matrice de deux lignes et trois colonnes par une matrice de trois lignes et deux colonnes.

Compétence : calcul matriciel avec trois boucles imbriquées.

#include <stdio.h>

int main(void)
{
    int a[2][3] = {
        {1, 2, 3},
        {4, 5, 6}
    };

    int b[3][2] = {
        {7, 8},
        {9, 10},
        {11, 12}
    };

    int resultat[2][2] = {0};

    for (int i = 0; i < 2; i++)
    {
        for (int j = 0; j < 2; j++)
        {
            for (int k = 0; k < 3; k++)
            {
                resultat[i][j] += a[i][k] * b[k][j];
            }
        }
    }

    for (int i = 0; i < 2; i++)
    {
        for (int j = 0; j < 2; j++)
        {
            printf("%d ", resultat[i][j]);
        }

        printf("\n");
    }

    return 0;
}
Exercice 27 — Créer et libérer une matrice dynamique

Créez une matrice dont le nombre de lignes et de colonnes est choisi par l’utilisateur.

Compétence : double pointeur et allocation dynamique en deux dimensions.

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int lignes;
    int colonnes;

    printf("Lignes et colonnes : ");
    scanf("%d %d", &lignes, &colonnes);

    if (lignes <= 0 || colonnes <= 0)
    {
        return 1;
    }

    int **matrice = malloc((size_t)lignes *
                           sizeof(*matrice));

    if (matrice == NULL)
    {
        return 1;
    }

    for (int i = 0; i < lignes; i++)
    {
        matrice[i] = malloc((size_t)colonnes *
                            sizeof(*matrice[i]));

        if (matrice[i] == NULL)
        {
            for (int k = 0; k < i; k++)
            {
                free(matrice[k]);
            }

            free(matrice);
            return 1;
        }
    }

    for (int i = 0; i < lignes; i++)
    {
        for (int j = 0; j < colonnes; j++)
        {
            matrice[i][j] = i + j;
            printf("%d ", matrice[i][j]);
        }

        printf("\n");
    }

    for (int i = 0; i < lignes; i++)
    {
        free(matrice[i]);
    }

    free(matrice);

    return 0;
}
Exercice 28 — Trier un tableau de chaînes

Triez plusieurs noms de villes par ordre alphabétique avec strcmp() et strcpy().

Compétence : tableau à deux dimensions et fonctions de string.h.

#include <stdio.h>
#include <string.h>

int main(void)
{
    char villes[5][30] = {
        "Toulouse",
        "Paris",
        "Lyon",
        "Marseille",
        "Bordeaux"
    };

    char temporaire[30];

    for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < 4 - i; j++)
        {
            if (strcmp(villes[j], villes[j + 1]) > 0)
            {
                strcpy(temporaire, villes[j]);
                strcpy(villes[j], villes[j + 1]);
                strcpy(villes[j + 1], temporaire);
            }
        }
    }

    for (int i = 0; i < 5; i++)
    {
        printf("%s\n", villes[i]);
    }

    return 0;
}
Exercice 29 — Trouver le deuxième plus grand élément

Trouvez la deuxième plus grande valeur distincte sans trier le tableau.

Compétence : suivi simultané de deux valeurs maximales.

#include <stdio.h>
#include <limits.h>

int main(void)
{
    int tab[] = {14, 9, 32, 18, 32, 27};
    int taille = sizeof(tab) / sizeof(tab[0]);

    int maximum = INT_MIN;
    int deuxieme = INT_MIN;

    for (int i = 0; i < taille; i++)
    {
        if (tab[i] > maximum)
        {
            deuxieme = maximum;
            maximum = tab[i];
        }
        else if (tab[i] > deuxieme &&
                 tab[i] != maximum)
        {
            deuxieme = tab[i];
        }
    }

    if (deuxieme == INT_MIN)
    {
        printf("Aucune deuxieme valeur distincte.\n");
    }
    else
    {
        printf("Deuxieme maximum : %d\n", deuxieme);
    }

    return 0;
}
Exercice 30 — Mini-projet de gestion des notes

Créez un programme qui saisit dynamiquement les notes d’une classe, calcule la moyenne, recherche la meilleure note et trie les résultats par ordre décroissant.

Compétences : allocation dynamique, fonctions, pointeurs, tri, moyenne et recherche du maximum.

#include <stdio.h>
#include <stdlib.h>

double calculerMoyenne(const double notes[], int taille)
{
    double somme = 0.0;

    for (int i = 0; i < taille; i++)
    {
        somme += notes[i];
    }

    return somme / taille;
}

double trouverMaximum(const double notes[], int taille)
{
    double maximum = notes[0];

    for (int i = 1; i < taille; i++)
    {
        if (notes[i] > maximum)
        {
            maximum = notes[i];
        }
    }

    return maximum;
}

void trierDecroissant(double notes[], int taille)
{
    for (int i = 0; i < taille - 1; i++)
    {
        for (int j = 0; j < taille - 1 - i; j++)
        {
            if (notes[j] < notes[j + 1])
            {
                double temp = notes[j];
                notes[j] = notes[j + 1];
                notes[j + 1] = temp;
            }
        }
    }
}

int main(void)
{
    int nombreEleves;

    printf("Nombre d'eleves : ");
    scanf("%d", &nombreEleves);

    if (nombreEleves <= 0)
    {
        return 1;
    }

    double *notes = malloc((size_t)nombreEleves *
                           sizeof(*notes));

    if (notes == NULL)
    {
        return 1;
    }

    for (int i = 0; i < nombreEleves; i++)
    {
        do
        {
            printf("Note de l'eleve %d : ", i + 1);
            scanf("%lf", &notes[i]);
        }
        while (notes[i] < 0.0 || notes[i] > 20.0);
    }

    printf("Moyenne : %.2f\n",
           calculerMoyenne(notes, nombreEleves));

    printf("Meilleure note : %.2f\n",
           trouverMaximum(notes, nombreEleves));

    trierDecroissant(notes, nombreEleves);

    printf("Classement : ");

    for (int i = 0; i < nombreEleves; i++)
    {
        printf("%.2f ", notes[i]);
    }

    free(notes);
    notes = NULL;

    return 0;
}

✅ Compétences couvertes par les 30 exercices

✔ Déclarer et parcourir un tableau
✔ Calculer somme et moyenne
✔ Rechercher minimum et maximum
✔ Compter des occurrences
✔ Utiliser les pointeurs
✔ Manipuler les chaînes
✔ Utiliser string.h
✔ Parcourir une matrice
✔ Additionner des matrices
✔ Transposer une matrice
✔ Multiplier des matrices
✔ Utiliser malloc()
✔ Utiliser realloc()
✔ Libérer la mémoire
✔ Trier un tableau
✔ Effectuer une recherche dichotomique
✔ Supprimer les doublons
✔ Fusionner des tableaux triés

Fiche de Rappel : Les Tableaux en Langage C

Les tableaux en C sont des structures de données qui permettent de stocker plusieurs éléments du même type dans un bloc de mémoire contigu. Ils sont particulièrement utiles lorsque vous devez manipuler une collection d’éléments, comme des nombres ou des chaînes de caractères.


1. Déclaration d’un tableau en C

Pour déclarer un tableau, il suffit de spécifier le type des éléments, le nom du tableau, et le nombre d’éléments à stocker dans ce tableau.

Syntaxe :

type nom_du_tableau[taille];

Exemple :

int tableau_entiers[10];  // Tableau de 10 entiers
float tableau_flottants[5];  // Tableau de 5 nombres flottants
char tableau_caracteres[20];  // Tableau de 20 caractères
  • Indice : Les tableaux en C sont indexés à partir de 0. Le premier élément d’un tableau se trouve à l’indice 0, le deuxième à l’indice 1, et ainsi de suite.

2. Initialisation d’un tableau

Un tableau peut être initialisé au moment de sa déclaration en spécifiant les valeurs à l’intérieur d’accolades {}.

Exemple d’initialisation :

int tableau[5] = {1, 2, 3, 4, 5};  // Tableau initialisé avec 5 valeurs

Si vous ne spécifiez pas le nombre d’éléments, le compilateur allouera automatiquement l’espace nécessaire pour toutes les valeurs spécifiées.

int tableau[] = {1, 2, 3, 4, 5};  // Taille déduite automatiquement

3. Accès aux éléments du tableau

L’accès aux éléments d’un tableau se fait en utilisant son indice.

Exemple :

int tableau[5] = {10, 20, 30, 40, 50};
printf("%d\n", tableau[0]);  // Affiche 10
printf("%d\n", tableau[4]);  // Affiche 50
  • Modification d’un élément :
tableau[2] = 100;  // Change la valeur à l'indice 2 en 100

4. Parcours d’un tableau

Pour parcourir un tableau, on utilise généralement une boucle for ou while.

Exemple avec for :

int tableau[5] = {10, 20, 30, 40, 50};
for (int i = 0; i < 5; i++) {
    printf("%d ", tableau[i]);  // Affiche les éléments du tableau
}

5. Tableaux multidimensionnels

En C, vous pouvez déclarer des tableaux à plusieurs dimensions (comme les matrices). Un tableau à 2 dimensions est similaire à une matrice, où les éléments sont organisés en lignes et en colonnes.

Déclaration :

type nom_du_tableau[taille1][taille2];

Exemple de tableau 2D (matrice) :

int matrice[3][3] = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};

Accès à un élément d’une matrice :

printf("%d\n", matrice[0][1]);  // Affiche 2

6. Tableaux de chaînes de caractères

Un tableau de caractères (ou chaîne de caractères) est un tableau d’éléments de type char.

Exemple :

char nom[10] = "Alice";  // Chaîne de caractères

Dans ce cas, le tableau contient les caractères 'A', 'l', 'i', 'c', 'e' suivis d’un caractère nul (\0), qui marque la fin de la chaîne.

Tableau de chaînes :

Vous pouvez créer un tableau de chaînes de caractères pour stocker plusieurs mots ou phrases.

char noms[3][10] = {"Alice", "Bob", "Charlie"};

7. Passage de tableau en paramètre

En C, lorsqu’un tableau est passé à une fonction, c’est l’adresse de son premier élément qui est transmise (par référence).

Exemple :

void afficher_tableau(int tableau[], int taille) {
    for (int i = 0; i < taille; i++) {
        printf("%d ", tableau[i]);
    }
    printf("\n");
}

int main() {
    int tableau[5] = {1, 2, 3, 4, 5};
    afficher_tableau(tableau, 5);  // Passe le tableau à la fonction
    return 0;
}

8. Mémoire et tableaux

Les tableaux en C occupent de la mémoire contiguë, c’est-à-dire que les éléments sont stockés les uns à la suite des autres.

Taille d’un tableau :

Vous pouvez utiliser l’opérateur sizeof pour obtenir la taille en octets d’un tableau, ou la taille d’un élément.

Exemple :

int tableau[5];
printf("Taille du tableau : %lu octets\n", sizeof(tableau));  // Taille totale en octets
printf("Taille d'un élément : %lu octets\n", sizeof(tableau[0]));  // Taille d'un élément

Pour obtenir le nombre d’éléments :

int taille = sizeof(tableau) / sizeof(tableau[0]);

9. Erreurs fréquentes avec les tableaux

  • Débordement de tableau : Accéder à un indice qui dépasse la taille du tableau peut entraîner des comportements indéfinis.
  • Par exemple, essayer d’accéder à tableau[5] alors que le tableau a été déclaré avec 5 éléments (tableau[0] à tableau[4]).
  • Non-initialisation des tableaux : Si un tableau n’est pas initialisé explicitement, les éléments peuvent contenir des valeurs indéfinies.

Résumé des principales commandes :

CommandeDescription
type nom[taille];Déclare un tableau de taille fixe.
nom[indice] = valeur;Modifie la valeur d’un élément du tableau.
int nom[][] = {{...},{...}}Déclare un tableau multidimensionnel.
sizeof(tableau)Renvoie la taille totale en octets d’un tableau.
nom[indice]Accède à l’élément à l’indice spécifié dans le tableau.

En résumé, les tableaux en C sont un moyen efficace de manipuler des collections d’éléments du même type, que ce soit en 1D (tableau simple) ou en 2D (tableau multidimensionnel). Leur gestion requiert de la prudence en ce qui concerne la gestion des indices et la mémoire allouée.






AZ

Recent Posts

Marchand de biens immobiliers : activités, opérations, stratégies d’achat-revente et gestion des projets

Le métier de marchand de biens immobiliers consiste à acquérir des biens dans une logique…

7 heures ago

Plan de communication événement : exemple complet, méthode et modèle à télécharger

Le succès d'un événement se prépare bien avant l'ouverture des portes. Une communication structurée permet…

1 jour ago

Chromatographie HPLC : 20 exercices corrigés pour maîtriser les calculs et l’interprétation

La chromatographie liquide haute performance (HPLC) est aujourd'hui l'une des techniques analytiques les plus utilisées…

5 jours ago

HPLC : guide pratique du laboratoire, outils, simulateurs, calculs et interprétation des chromatogrammes

La HPLC (Chromatographie Liquide Haute Performance) est aujourd'hui l'une des techniques analytiques les plus utilisées…

1 semaine ago

Bilan prévisionnel sci gratuit : modèles Excel gratuits

Créer une SCI répond souvent à un projet de long terme. Certains souhaitent acquérir un…

1 semaine ago

Budget mariage : modèles Excel, calculateur, planning et guide complet

Organiser un mariage est une aventure aussi enthousiasmante qu'exigeante. Derrière chaque cérémonie réussie se cachent…

1 semaine ago

This website uses cookies.