Langage C/C++

Pointeurs en C – Exercices Corrigés avec Cas Avancés

×

Recommandés

Guide Complet : Double Pointeur en C
Les doubles pointeurs (ou pointeurs de...
En savoir plus
Malloc contre Calloc en C : Guide...
Les fonctions malloc et calloc sont...
En savoir plus
Fiche Pratique : Réussir un QCM en...
Un questionnaire à choix multiple (QCM)...
En savoir plus
La structure d’un programme en langage C
Le langage C est idéal pour...
En savoir plus
Comment mettre au carré un nombre en...
Dans ce tutoriel, nous allons calculer...
En savoir plus
Cours PDF langage C / initiation à...
Dennis Ritchie a conçu et implémenté...
En savoir plus

Ce guide propose des exercices corrigés sur les pointeurs en C, allant des bases aux cas avancés. Il vise à renforcer la compréhension de concepts tels que la manipulation de mémoire, les pointeurs de fonctions, les chaînes de caractères dynamiques et les structures.


Exercice 1 : Déréférencement Basique

Énoncé :

Créez un programme qui utilise un pointeur pour afficher et modifier la valeur d’une variable.

Solution :

#include <stdio.h>

int main() {
    int a = 10;
    int *p = &a;

    printf("Valeur initiale de a : %d\n", *p);  // Afficher la valeur via le pointeur

    *p = 20;  // Modifier la valeur via le pointeur
    printf("Nouvelle valeur de a : %d\n", a);

    return 0;
}

Points Clés :

  • Un pointeur permet de lire et modifier directement la valeur de la variable à laquelle il est lié.

Exercice 2 : Échanger Deux Variables

Énoncé :

Écrivez une fonction qui échange les valeurs de deux variables en utilisant des pointeurs.

Solution :

#include <stdio.h>

void swap(int *x, int *y) {
    int temp = *x;
    *x = *y;
    *y = temp;
}

int main() {
    int a = 5, b = 10;

    printf("Avant échange : a = %d, b = %d\n", a, b);
    swap(&a, &b);  // Passer les adresses
    printf("Après échange : a = %d, b = %d\n", a, b);

    return 0;
}

Points Clés :

  • La fonction utilise les adresses des variables pour modifier leurs valeurs directement.

Exercice 3 : Tableaux et Pointeurs

Énoncé :

Implémentez un programme qui affiche les éléments d’un tableau en utilisant des pointeurs.

Solution :

#include <stdio.h>

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    int *p = arr;

    for (int i = 0; i < 5; i++) {
        printf("Élément %d : %d\n", i, *(p + i));  // Accès via le pointeur
    }

    return 0;
}

Points Clés :

  • *(p + i) est équivalent à arr[i].

Exercice 4 : Chaînes de Caractères Dynamiques

Énoncé :

Écrivez un programme qui copie une chaîne de caractères dans une mémoire allouée dynamiquement.

Solution :

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

int main() {
    char source[] = "Pointeurs en C";
    char *dest = (char *)malloc((strlen(source) + 1) * sizeof(char));

    if (dest == NULL) {
        printf("Erreur d'allocation mémoire\n");
        return 1;
    }

    strcpy(dest, source);
    printf("Chaîne copiée : %s\n", dest);

    free(dest);  // Libérer la mémoire
    return 0;
}

Points Clés :

  • malloc est utilisé pour allouer suffisamment de mémoire.
  • N’oubliez jamais de libérer la mémoire allouée avec free.

Exercice 5 : Tableaux 2D Dynamiques

Énoncé :

Allouez dynamiquement un tableau 2D, assignez des valeurs, puis affichez-les.

Solution :

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

int main() {
    int rows = 3, cols = 4;
    int **matrix = (int **)malloc(rows * sizeof(int *));

    for (int i = 0; i < rows; i++) {
        matrix[i] = (int *)malloc(cols * sizeof(int));
    }

    // Remplir le tableau
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            matrix[i][j] = i * cols + j;
        }
    }

    // Afficher le tableau
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            printf("%d ", matrix[i][j]);
        }
        printf("\n");
    }

    // Libérer la mémoire
    for (int i = 0; i < rows; i++) {
        free(matrix[i]);
    }
    free(matrix);

    return 0;
}

Points Clés :

  • Les tableaux 2D nécessitent une double allocation dynamique.
  • Chaque ligne doit être libérée individuellement avant de libérer le tableau principal.

Exercice 6 : Pointeurs de Fonction

Énoncé :

Implémentez un programme qui utilise un pointeur de fonction pour appeler dynamiquement des fonctions.

Solution :

#include <stdio.h>

void add(int a, int b) {
    printf("Addition : %d\n", a + b);
}

void multiply(int a, int b) {
    printf("Multiplication : %d\n", a * b);
}

int main() {
    void (*operation)(int, int);

    operation = add;
    operation(5, 3);  // Appeler add via le pointeur

    operation = multiply;
    operation(5, 3);  // Appeler multiply via le pointeur

    return 0;
}

Points Clés :

  • Un pointeur de fonction peut stocker l’adresse de différentes fonctions ayant la même signature.

Exercice 7 : Pointeurs Dangling

Énoncé :

Montrez comment éviter un pointeur dangling lors de l’utilisation de free.

Solution :

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

int main() {
    int *p = (int *)malloc(sizeof(int));
    *p = 42;

    printf("Valeur : %d\n", *p);

    free(p);
    p = NULL;  // Réinitialiser le pointeur pour éviter un pointeur dangling

    return 0;
}

Points Clés :

  • Après avoir libéré une mémoire, réinitialisez toujours le pointeur à NULL.

Exercice 8 : Accès Concurrent avec Mutex

Énoncé :

Protégez un tableau partagé entre plusieurs threads avec un mutex.

Solution :

#include <stdio.h>
#include <pthread.h>

#define SIZE 5

int arr[SIZE] = {0};
pthread_mutex_t lock;

void *increment(void *arg) {
    pthread_mutex_lock(&lock);
    for (int i = 0; i < SIZE; i++) {
        arr[i]++;
    }
    pthread_mutex_unlock(&lock);
    return NULL;
}

int main() {
    pthread_t t1, t2;

    pthread_mutex_init(&lock, NULL);

    pthread_create(&t1, NULL, increment, NULL);
    pthread_create(&t2, NULL, increment, NULL);

    pthread_join(t1, NULL);
    pthread_join(t2, NULL);

    pthread_mutex_destroy(&lock);

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

    return 0;
}

Points Clés :

  • Les mutex assurent un accès sécurisé aux ressources partagées entre threads.

Suite : Exercices Avancés et Complexes avec les Pointeurs en C

Cette suite d’exercices couvre des concepts encore plus avancés avec les pointeurs en C. Les exercices impliquent la gestion de structures imbriquées, les pointeurs void, les allocations complexes, et les erreurs intentionnelles pour apprendre à déboguer.


Exercice 9 : Manipuler des Structures avec Pointeurs

Énoncé :

Créez une structure représentant un étudiant (nom, âge, note moyenne) et utilisez un pointeur pour accéder et modifier ses champs.

Solution :

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

typedef struct {
    char name[50];
    int age;
    float average;
} Student;

int main() {
    Student s1;
    Student *ptr = &s1;

    // Modifier via pointeur
    strcpy(ptr->name, "Alice");
    ptr->age = 20;
    ptr->average = 17.5;

    // Afficher les valeurs
    printf("Nom : %s\n", ptr->name);
    printf("Âge : %d\n", ptr->age);
    printf("Moyenne : %.2f\n", ptr->average);

    return 0;
}

Points Clés :

  • Utilisez l’opérateur -> pour accéder aux membres d’une structure via un pointeur.
  • Combinez les structures avec des pointeurs pour gérer des données dynamiques.

Exercice 10 : Allocation Dynamique de Structures

Énoncé :

Allouez dynamiquement un tableau de structures Student pour gérer plusieurs étudiants.

Solution :

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

typedef struct {
    char name[50];
    int age;
    float average;
} Student;

int main() {
    int n = 3;
    Student *students = (Student *)malloc(n * sizeof(Student));

    if (students == NULL) {
        printf("Erreur d'allocation mémoire\n");
        return 1;
    }

    // Initialiser les données
    for (int i = 0; i < n; i++) {
        snprintf(students[i].name, 50, "Etudiant %d", i + 1);
        students[i].age = 18 + i;
        students[i].average = 15.0 + i;
    }

    // Afficher les données
    for (int i = 0; i < n; i++) {
        printf("Nom : %s, Âge : %d, Moyenne : %.2f\n",
               students[i].name, students[i].age, students[i].average);
    }

    free(students);
    return 0;
}

Points Clés :

  • Chaque élément du tableau est une structure.
  • Assurez-vous de libérer la mémoire après utilisation.

Exercice 11 : Utilisation des Pointeurs void

Énoncé :

Utilisez un pointeur void pour créer une fonction générique qui affiche différentes valeurs.

Solution :

#include <stdio.h>

void printValue(void *ptr, char type) {
    switch (type) {
        case 'i': // Entier
            printf("Valeur entière : %d\n", *(int *)ptr);
            break;
        case 'f': // Float
            printf("Valeur flottante : %.2f\n", *(float *)ptr);
            break;
        case 'c': // Caractère
            printf("Caractère : %c\n", *(char *)ptr);
            break;
        default:
            printf("Type non reconnu\n");
    }
}

int main() {
    int a = 10;
    float b = 3.14;
    char c = 'A';

    printValue(&a, 'i');
    printValue(&b, 'f');
    printValue(&c, 'c');

    return 0;
}

Points Clés :

  • Les pointeurs void permettent une flexibilité maximale, mais nécessitent un transtypage explicite.

Exercice 12 : Création d’une Liste Chaînée

Énoncé :

Implémentez une liste chaînée pour stocker des entiers.

Solution :

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

typedef struct Node {
    int data;
    struct Node *next;
} Node;

// Ajouter un élément en tête
Node *addNode(Node *head, int value) {
    Node *newNode = (Node *)malloc(sizeof(Node));
    newNode->data = value;
    newNode->next = head;
    return newNode;
}

// Afficher la liste
void printList(Node *head) {
    Node *current = head;
    while (current != NULL) {
        printf("%d -> ", current->data);
        current = current->next;
    }
    printf("NULL\n");
}

// Libérer la liste
void freeList(Node *head) {
    Node *current = head;
    while (current != NULL) {
        Node *next = current->next;
        free(current);
        current = next;
    }
}

int main() {
    Node *head = NULL;

    head = addNode(head, 10);
    head = addNode(head, 20);
    head = addNode(head, 30);

    printList(head);
    freeList(head);

    return 0;
}

Points Clés :

  • Utilisez des pointeurs pour relier les nœuds.
  • Gérez soigneusement la libération de mémoire pour éviter les fuites.

Exercice 13 : Fonction Générique avec Pointeurs

Énoncé :

Créez une fonction générique pour trier un tableau en fonction de la taille des éléments.

Solution :

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

void sort(void *arr, size_t n, size_t size, int (*cmp)(const void *, const void *)) {
    char *base = (char *)arr;
    for (size_t i = 0; i < n - 1; i++) {
        for (size_t j = i + 1; j < n; j++) {
            if (cmp(base + i * size, base + j * size) > 0) {
                char temp[size];
                memcpy(temp, base + i * size, size);
                memcpy(base + i * size, base + j * size, size);
                memcpy(base + j * size, temp, size);
            }
        }
    }
}

int compareInt(const void *a, const void *b) {
    return (*(int *)a - *(int *)b);
}

int main() {
    int arr[] = {5, 2, 9, 1, 6};
    size_t n = sizeof(arr) / sizeof(arr[0]);

    sort(arr, n, sizeof(int), compareInt);

    for (size_t i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }

    return 0;
}

Points Clés :

  • Les fonctions génériques rendent le code réutilisable.
  • Combinez void * avec des fonctions de comparaison pour généraliser les algorithmes.

Recommandés

Guide : L'Allocation Dynamique en C
L'allocation dynamique en C permet de...
En savoir plus
Optimisation d'une Fonction Récursive
L'optimisation d'une fonction récursive consiste à...
En savoir plus
Les Pointeurs en Langage C : Astuces...
Les pointeurs sont l'un des aspects...
En savoir plus
Appeler une Fonction en C - Exercices...
L'un des concepts fondamentaux en programmation...
En savoir plus
Conversion Hexadécimal en Binaire en Langage C...
La conversion des nombres hexadécimaux en...
En savoir plus
Calcul de Puissance en C Sans pow()...
Le calcul de puissance est une...
En savoir plus
AZ

Recent Posts

Classification des Documents : Organiser et Automatiser la Gestion Documentaire

Dans toute organisation moderne — entreprise, association, service administratif ou bureau de projet — la…

2 jours ago

Modèle de Bilan Actif Passif sur Excel : Concevoir un tableau comptable clair et automatisé

Dans la pratique comptable, le bilan constitue l’un des documents les plus fondamentaux pour comprendre…

2 jours ago

Fiche Méthode analyse linéaire + guide complet pour la réussir

L’analyse linéaire impressionne souvent plus qu’elle ne le devrait. Au moment d’aborder l’oral du bac…

3 jours ago

Analyse linéaire au bac français : méthode complète, exemples et conseils pour réussir l’oral

L’analyse linéaire occupe une place centrale à l’oral du bac français. C’est l’exercice qui permet…

3 jours ago

Créer une fiche de suivi en ligne : générateur personnalisable à imprimer

Créer une fiche de suivi claire et adaptée à son activité prend souvent plus de…

3 jours ago

Préparation physique football avec ballon : Fiche Word utile

Comment améliorer sa condition physique tout en travaillant la technique Quand on parle de préparation…

3 jours ago

This website uses cookies.