Parcours de tableaux à l'aide de pointeurs

CBeginner
Pratiquer maintenant

Introduction

L'arithmétique des pointeurs est une fonctionnalité puissante en C qui vous permet de manipuler les adresses mémoire en ajoutant ou en soustrayant des valeurs. L'une des applications les plus courantes de l'arithmétique des pointeurs est la traversée de tableaux. En utilisant des pointeurs, nous pouvons parcourir efficacement les tableaux dans les deux sens, avant et arrière.

Dans ce lab (atelier), vous apprendrez à créer et à initialiser des tableaux, à configurer des pointeurs pour accéder aux éléments des tableaux et à utiliser l'arithmétique des pointeurs pour parcourir les tableaux. Cette technique est fondamentale en programmation C et constitue la base de nombreuses opérations avancées de manipulation de données.

Création d'un programme C de base

Commençons par créer un nouveau fichier C dans l'éditeur VSCode. Ce fichier contiendra notre programme principal pour la traversée de tableaux à l'aide de pointeurs.

  1. Dans le WebIDE, localisez le panneau de l'Explorateur sur le côté gauche et accédez au répertoire ~/project.

  2. Cliquez avec le bouton droit sur le dossier project et sélectionnez "Nouveau fichier". Nommez le fichier main.c.

  3. Copiez la structure de base d'un programme C suivante dans le fichier :

#include <stdio.h>

int main() {
    printf("Array Traversal using Pointers\n");

    return 0;
}
  1. Enregistrez le fichier en appuyant sur Ctrl+S ou en utilisant Fichier > Enregistrer dans le menu.

  2. Compilons et exécutons ce programme pour nous assurer que tout est correctement configuré. Ouvrez un terminal dans le WebIDE en sélectionnant Terminal > Nouveau terminal dans le menu, puis exécutez :

cd ~/project
gcc main.c -o main
./main

Vous devriez voir la sortie suivante :

Array Traversal using Pointers

Cela confirme que votre environnement de développement C fonctionne correctement. Dans les étapes suivantes, nous modifierons ce programme pour qu'il fonctionne avec des tableaux et des pointeurs.

Déclaration et initialisation de tableaux et de pointeurs

Dans cette étape, nous apprendrons à déclarer un tableau et un pointeur, qui sont les composants fondamentaux pour la traversée de tableaux à l'aide de pointeurs.

Compréhension des tableaux et des pointeurs

Un tableau en C est une collection d'éléments du même type stockés dans des emplacements mémoire contigus. Par exemple, un tableau d'entiers avec 5 éléments réservera de l'espace pour 5 entiers en mémoire, l'un après l'autre.

Un pointeur est une variable qui stocke l'adresse mémoire d'une autre variable. Nous pouvons utiliser des pointeurs pour accéder indirectement à la valeur stockée à un emplacement mémoire particulier.

Modifions notre fichier main.c pour inclure un tableau et un pointeur :

#include <stdio.h>

int main() {
    printf("Array Traversal using Pointers\n\n");

    // Declare and initialize an array of 5 integers
    int arr[5] = {10, 20, 30, 40, 50};

    // Declare a pointer of integer type
    int *ptr;

    // Print the array elements using array notation
    printf("Array elements using array notation:\n");
    for(int i = 0; i < 5; i++) {
        printf("arr[%d] = %d\n", i, arr[i]);
    }

    return 0;
}

Dans ce code :

  • Nous avons déclaré un tableau d'entiers arr avec 5 éléments et l'avons initialisé avec les valeurs 10, 20, 30, 40 et 50.
  • Nous avons déclaré un pointeur d'entiers ptr qui sera utilisé plus tard pour pointer vers les éléments du tableau.
  • Nous avons affiché les éléments du tableau en utilisant la notation traditionnelle des tableaux.

Compilez et exécutez le programme pour voir les éléments du tableau :

gcc main.c -o main
./main

Vous devriez voir la sortie suivante :

Array Traversal using Pointers

Array elements using array notation:
arr[0] = 10
arr[1] = 20
arr[2] = 30
arr[3] = 40
arr[4] = 50

Dans l'étape suivante, nous connecterons le pointeur au tableau et accéderons aux éléments du tableau à l'aide du pointeur.

Liaison des pointeurs avec des tableaux et parcours en avant

Dans cette étape, nous établirons la connexion entre notre pointeur et le tableau, puis nous utiliserons le pointeur pour parcourir le tableau dans le sens avant.

Liaison d'un pointeur à un tableau

En C, le nom d'un tableau sans indice représente l'adresse du premier élément du tableau. Cela signifie que nous pouvons assigner directement cette adresse à une variable pointeur.

Modifions notre fichier main.c pour lier le pointeur au tableau et le parcourir :

#include <stdio.h>

int main() {
    printf("Array Traversal using Pointers\n\n");

    // Declare and initialize an array of 5 integers
    int arr[5] = {10, 20, 30, 40, 50};

    // Declare a pointer of integer type
    int *ptr;

    // Assign the address of the first element of the array to the pointer
    ptr = arr;  // This is equivalent to ptr = &arr[0]

    // Print the array elements using array notation
    printf("Array elements using array notation:\n");
    for(int i = 0; i < 5; i++) {
        printf("arr[%d] = %d\n", i, arr[i]);
    }

    // Print the array elements using pointer notation
    printf("\nArray elements using pointer notation (forward traversal):\n");
    for(int i = 0; i < 5; i++) {
        printf("*(ptr + %d) = %d\n", i, *(ptr + i));
    }

    return 0;
}

Dans ce code mis à jour :

  • Nous avons assigné l'adresse du premier élément du tableau arr au pointeur ptr.
  • Nous avons ajouté une nouvelle boucle qui parcourt le tableau en utilisant l'arithmétique des pointeurs.
  • L'expression *(ptr + i) accède à la valeur située à l'emplacement mémoire ptr + i. Lorsque i est égal à 0, il s'agit du premier élément du tableau ; lorsque i est égal à 1, il s'agit du deuxième élément, et ainsi de suite.

Compilez et exécutez le programme pour voir les résultats :

gcc main.c -o main
./main

Vous devriez voir la sortie suivante :

Array Traversal using Pointers

Array elements using array notation:
arr[0] = 10
arr[1] = 20
arr[2] = 30
arr[3] = 40
arr[4] = 50

Array elements using pointer notation (forward traversal):
*(ptr + 0) = 10
*(ptr + 1) = 20
*(ptr + 2) = 30
*(ptr + 3) = 40
*(ptr + 4) = 50

Remarquez que les deux méthodes produisent la même sortie. Cela démontre que l'arithmétique des pointeurs peut être utilisée pour accéder aux éléments d'un tableau tout comme l'indexation traditionnelle des tableaux.

Implémentation de l'incrémentation de pointeur pour le parcours de tableau

Dans l'étape précédente, nous avons accédé aux éléments d'un tableau en utilisant l'expression *(ptr + i). Bien que cela fonctionne parfaitement, le langage C propose un moyen plus concis de parcourir un tableau à l'aide de pointeurs : l'opérateur d'incrémentation (++).

Lorsque nous incrémentons un pointeur, il se déplace vers l'emplacement mémoire suivant en fonction de la taille du type de données vers lequel il pointe. Pour un pointeur d'entier, l'incrémenter le fait passer au prochain entier en mémoire.

Modifions notre fichier main.c pour utiliser l'incrémentation de pointeur pour la traversée du tableau :

#include <stdio.h>

int main() {
    printf("Array Traversal using Pointers\n\n");

    // Declare and initialize an array of 5 integers
    int arr[5] = {10, 20, 30, 40, 50};

    // Declare and initialize a pointer to the first element of the array
    int *ptr = arr;  // Same as ptr = &arr[0]

    // Print the array elements using pointer incrementation
    printf("Array elements using pointer incrementation:\n");
    for(int i = 0; i < 5; i++) {
        printf("*ptr = %d\n", *ptr);
        ptr++;  // Move the pointer to the next element
    }

    // Reset the pointer to the beginning of the array
    ptr = arr;

    // Print all elements in a single line using pointer incrementation
    printf("\nAll elements in a single line: ");
    for(int i = 0; i < 5; i++) {
        printf("%d ", *ptr++);  // Print and then increment
    }
    printf("\n");

    return 0;
}

Dans ce code mis à jour :

  • Nous initialisons le pointeur ptr directement lors de sa déclaration.
  • À l'intérieur de la première boucle, nous utilisons *ptr pour accéder à l'élément actuel, puis ptr++ pour passer à l'élément suivant.
  • Après la première boucle, nous réinitialisons ptr pour qu'il pointe de nouveau au début du tableau.
  • Dans la deuxième boucle, nous utilisons l'opérateur d'incrémentation postfixée *ptr++, qui utilise d'abord la valeur actuelle de ptr, puis l'incrémente.

Compilez et exécutez le programme pour voir les résultats :

gcc main.c -o main
./main

Vous devriez voir la sortie suivante :

Array Traversal using Pointers

Array elements using pointer incrementation:
*ptr = 10
*ptr = 20
*ptr = 00
*ptr = 40
*ptr = 50

All elements in a single line: 10 20 30 40 50

Cela démontre comment utiliser l'incrémentation de pointeur pour parcourir un tableau. Le point clé est que ptr++ prend automatiquement en compte la taille du type de données lorsqu'il se déplace vers l'élément suivant.

Implémentation du parcours en arrière en utilisant la décrémentation de pointeur

Dans les étapes précédentes, nous avons parcouru le tableau dans le sens avant. Maintenant, apprenons à parcourir le tableau dans le sens inverse en utilisant la décrémentation de pointeur.

Pour la traversée en arrière, nous devons :

  1. Initialiser le pointeur pour qu'il pointe vers le dernier élément du tableau.
  2. Décrémenter le pointeur pour nous déplacer en arrière dans le tableau.

Modifions notre fichier main.c pour implémenter la traversée en arrière :

#include <stdio.h>

int main() {
    printf("Array Traversal using Pointers\n\n");

    // Declare and initialize an array of 5 integers
    int arr[5] = {10, 20, 30, 40, 50};

    // Forward traversal using pointer increment
    int *ptr = arr;
    printf("Forward traversal using pointer increment:\n");
    for(int i = 0; i < 5; i++) {
        printf("%d ", *ptr);
        ptr++;
    }
    printf("\n\n");

    // Backward traversal using pointer decrement
    // Point to the last element of the array
    ptr = &arr[4];  // or ptr = arr + 4

    printf("Backward traversal using pointer decrement:\n");
    for(int i = 0; i < 5; i++) {
        printf("%d ", *ptr);
        ptr--;  // Move the pointer to the previous element
    }
    printf("\n\n");

    // Alternative approach: Start from the last element and decrement in the loop condition
    printf("Alternative backward traversal approach:\n");
    for(ptr = &arr[4]; ptr >= arr; ptr--) {
        printf("%d ", *ptr);
    }
    printf("\n");

    return 0;
}

Dans ce code mis à jour :

  • Nous effectuons d'abord une traversée en avant en utilisant l'incrémentation de pointeur.
  • Pour la traversée en arrière, nous positionnons le pointeur sur le dernier élément du tableau en utilisant ptr = &arr[4].
  • À l'intérieur de la boucle, nous affichons l'élément actuel, puis nous décrémentons le pointeur en utilisant ptr--.
  • Nous montrons également une méthode alternative où la décrémentation fait partie de l'instruction de mise à jour de la boucle for.

Compilez et exécutez le programme pour voir les résultats :

gcc main.c -o main
./main

Vous devriez voir la sortie suivante :

Array Traversal using Pointers

Forward traversal using pointer increment:
10 20 30 40 50

Backward traversal using pointer decrement:
50 40 30 20 10

Alternative backward traversal approach:
50 40 30 20 10

Cela démontre comment parcourir un tableau dans les deux sens, avant et arrière, en utilisant l'arithmétique des pointeurs. La capacité d'incrémenter et de décrémenter les pointeurs facilite le déplacement dans les tableaux dans n'importe quelle direction.

Résumé

Dans ce laboratoire, vous avez appris à parcourir des tableaux à l'aide de pointeurs en programmation C. Voici les concepts clés que nous avons abordés :

  1. Bases des tableaux et des pointeurs :

    • Les tableaux en C stockent les éléments dans des emplacements mémoire contigus.
    • Les pointeurs stockent des adresses mémoire et peuvent être utilisés pour accéder à ces emplacements.
  2. Relation entre pointeurs et tableaux :

    • Le nom du tableau (sans indice) représente l'adresse du premier élément.
    • Nous pouvons assigner cette adresse à un pointeur pour établir une connexion avec le tableau.
  3. Techniques de traversée en avant :

    • En utilisant l'arithmétique des pointeurs : *(ptr + i)
    • En utilisant l'incrémentation de pointeur : *ptr suivi de ptr++
    • En combinant la déréférencement et l'incrémentation : *ptr++
  4. Techniques de traversée en arrière :

    • Initialiser le pointeur sur le dernier élément : ptr = &arr[size-1]
    • Utiliser la décrémentation de pointeur : ptr-- pour se déplacer en arrière
    • La condition de boucle peut vérifier quand le pointeur atteint le début du tableau.

L'arithmétique des pointeurs est une fonctionnalité puissante en C qui permet une manipulation efficace de la mémoire et offre une grande flexibilité lors de la manipulation de tableaux et d'autres structures de données. Cette technique constitue la base pour des concepts de programmation plus avancés tels que l'allocation dynamique de mémoire, les listes chaînées et d'autres structures de données complexes.