Langage C/C++

Déclaration de Tableau Dynamique en C avec Pointeurs : Astuces, Erreurs Courantes et Exercices Détaillés

Les tableaux dynamiques en C sont des structures de données flexibles et puissantes qui permettent aux programmeurs de gérer efficacement la mémoire et de manipuler des collections de données de taille variable. Dans cet article, nous explorerons en détail la déclaration et l’utilisation de tableaux dynamiques en C en utilisant des pointeurs. Nous examinerons également certaines astuces, les erreurs courantes à éviter et proposerons des exercices pour renforcer votre compréhension.

Déclaration de Tableau Dynamique en C
  • En C, un tableau dynamique est un tableau dont la taille peut être déterminée à l’exécution plutôt qu’à la compilation.
  • La méthode classique pour créer un tableau dynamique consiste à utiliser la fonction malloc() pour allouer de la mémoire.
  • Voici un exemple de déclaration d’un tableau dynamique en C :
   int *tab;
   int taille = 10;
   tab = (int *)malloc(taille * sizeof(int));
  • Cette déclaration crée un tableau dynamique d’entiers de taille 10.
  • N’oubliez pas de libérer la mémoire une fois que vous avez fini d’utiliser le tableau en utilisant la fonction free().
Utilisation des Tableaux Dynamiques
  • Une fois que le tableau dynamique est alloué, vous pouvez l’utiliser comme n’importe quel autre tableau en C.
  • Vous pouvez accéder aux éléments du tableau en utilisant l’opérateur de déréférencement (*).
  • Voici un exemple montrant comment initialiser et accéder aux éléments d’un tableau dynamique :
   for (int i = 0; i < taille; i++) {
       tab[i] = i * 2;
   }
  • Vous pouvez également redimensionner un tableau dynamique en utilisant la fonction realloc().
  • Assurez-vous de vérifier si l’allocation de mémoire a réussi pour éviter les erreurs de segmentation.
Astuces pour Manipuler les Tableaux Dynamiques
  • Toujours vérifier si l’allocation de mémoire a réussi en vérifiant si le pointeur renvoyé par malloc() ou realloc() est NULL.
  • Libérer la mémoire dès que vous avez fini d’utiliser le tableau pour éviter les fuites de mémoire.
  • Utilisez des macros ou des constantes pour définir la taille des tableaux dynamiques afin de rendre votre code plus lisible et plus facile à maintenir.
Erreurs Courantes à Éviter
  • Oublier de libérer la mémoire allouée pour le tableau dynamique peut entraîner des fuites de mémoire.
  • Accéder à des éléments en dehors des limites du tableau peut provoquer des comportements indéfinis.
  • Ne pas vérifier si l’allocation de mémoire a réussi peut entraîner des erreurs de segmentation.

Voici comment je pourrais présenter les erreurs à éviter en utilisant des exemples de code illustrant le bon et le mauvais code :

Erreurs Courantes à Éviter lors de l’Utilisation de Tableaux Dynamiques en C
  1. Fuite de Mémoire : Mauvais Code :
   int *tab = (int *)malloc(10 * sizeof(int));
   // Utilisation du tableau...
   // Oubli de libérer la mémoire

Bon Code :

   int *tab = (int *)malloc(10 * sizeof(int));
   // Utilisation du tableau...
   free(tab); // Libération de la mémoire
  1. Accès Hors Limites : Mauvais Code :
   int *tab = (int *)malloc(10 * sizeof(int));
   tab[10] = 42; // Accès hors limites

Bon Code :

   int *tab = (int *)malloc(10 * sizeof(int));
   tab[9] = 42; // Accès valide à l'indice 9
  1. Non-Vérification de l’Allocation de Mémoire : Mauvais Code :
   int *tab = (int *)malloc(10 * sizeof(int));
   // Non-vérification de l'allocation de mémoire

Bon Code :

   int *tab = (int *)malloc(10 * sizeof(int));
   if (tab == NULL) {
       printf("Erreur lors de l'allocation de mémoire");
       return 1;
   }
  1. Redimensionnement Incorrect du Tableau : Mauvais Code :
   int *tab = (int *)malloc(10 * sizeof(int));
   tab = (int *)realloc(tab, 20 * sizeof(int)); // Redimensionnement incorrect

Bon Code :

   int *tab = (int *)malloc(10 * sizeof(int));
   int *nouveau_tab = (int *)realloc(tab, 20 * sizeof(int)); // Redimensionnement correct
   if (nouveau_tab == NULL) {
       // Gestion de l'échec du redimensionnement
   } else {
       tab = nouveau_tab;
   }
  1. Mauvaise Utilisation des Pointeurs : Mauvais Code :
   int *tab = (int *)malloc(10 * sizeof(int));
   free(&tab); // Utilisation incorrecte du pointeur

Bon Code :

   int *tab = (int *)malloc(10 * sizeof(int));
   free(tab); // Utilisation correcte du pointeur

En évitant ces erreurs courantes et en suivant les bonnes pratiques de programmation, vous pouvez écrire un code plus robuste et plus fiable lors de l’utilisation de tableaux dynamiques en C.


Produit de Matrices Carrées


Écrivez un programme en C qui prend en entrée deux matrices carrées de taille m×n et n×p et calcule leur produit. Utilisez des pointeurs pour manipuler les matrices.

Solution :

#include <stdio.h>

void matrixProduct(int *A, int *B, int *C, int n) {
    int i, j, k;
    for (i = 0; i < n; i++) {
        for (j = 0; j < n; j++) {
            *(C + i*n + j) = 0;
            for (k = 0; k < n; k++) {
                *(C + i*n + j) += *(A + i*n + k) * *(B + k*n + j);
            }
        }
    }
}

int main() {
    int n = 3; // Taille des matrices carrées
    int A[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
    int B[3][3] = {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}};
    int C[3][3];

    // Calculer le produit
    matrixProduct((int *)A, (int *)B, (int *)C, n);

    // Afficher le résultat
    printf("Produit de A et B :\n");
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            printf("%d ", C[i][j]);
        }
        printf("\n");
    }

    return 0;
}
Produit de Matrices Rectangulaires

Écrivez un programme en C qui prend en entrée deux matrices de taille m×nm \times nm×n et n×pn \times pn×p et calcule leur produit. Assurez-vous que les dimensions des matrices sont compatibles pour effectuer le produit.

#include <stdio.h>

void matrixProduct(int *A, int *B, int *C, int m, int n, int p) {
    int i, j, k;
    for (i = 0; i < m; i++) {
        for (j = 0; j < p; j++) {
            *(C + i*p + j) = 0;
            for (k = 0; k < n; k++) {
                *(C + i*p + j) += *(A + i*n + k) * *(B + k*p + j);
            }
        }
    }
}

int main() {
    int m = 2, n = 3, p = 2; // Tailles des matrices
    int A[2][3] = {{1, 2, 3}, {4, 5, 6}};
    int B[3][2] = {{7, 8}, {9, 10}, {11, 12}};
    int C[2][2];

    // Calculer le produit
    matrixProduct((int *)A, (int *)B, (int *)C, m, n, p);

    // Afficher le résultat
    printf("Produit de A et B :\n");
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < p; j++) {
            printf("%d ", C[i][j]);
        }
        printf("\n");
    }

    return 0;
}
Calcul de la Transposée

Écrivez une fonction en C qui prend en entrée une matrice A de taille m×n et calcule sa transposée AT. Utilisez des pointeurs pour manipuler les matrices.

#include <stdio.h>

void transpose(int *A, int *A_T, int m, int n) {
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            *(A_T + j*m + i) = *(A + i*n + j);
        }
    }
}

int main() {
    int m = 3, n = 2; // Taille de la matrice A
    int A[3][2] = {{1, 2}, {3, 4}, {5, 6}};
    int A_T[2][3];

    // Calculer la transposée
    transpose((int *)A, (int *)A_T, m, n);

    // Afficher le résultat
    printf("Matrice A :\n");
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            printf("%d ", A[i][j]);
        }
        printf("\n");
    }

    printf("\nTransposée de A :\n");
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            printf("%d ", A_T[i][j]);
        }
        printf("\n");
    }

    return 0;
}
Produit de Matrices avec Allocation Dynamique

Modifiez le programme de l’exercice 1 pour utiliser l’allocation dynamique de mémoire pour les matrices. Assurez-vous de libérer la mémoire correctement après avoir terminé le calcul du produit.

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

// Fonction pour calculer le produit de deux matrices rectangulaires
void matrixProduct(int **A, int **B, int **C, int m, int n, int p) {
    int i, j, k;

    // Parcourir les lignes de la première matrice
    for (i = 0; i < m; i++) {
        // Parcourir les colonnes de la deuxième matrice
        for (j = 0; j < p; j++) {
            // Initialiser l'élément (i, j) de la matrice résultante à 0
            C[i][j] = 0;
            // Parcourir les colonnes de la première matrice / les lignes de la deuxième matrice
            for (k = 0; k < n; k++) {
                // Calculer le produit et l'ajouter à l'élément (i, j) de la matrice résultante
                C[i][j] += A[i][k] * B[k][j];
            }
        }
    }
}

int main() {
    int m = 2, n = 3, p = 2; // Tailles des matrices
    int **A, **B, **C;
    int i, j, k;

    // Allocation dynamique de mémoire pour les matrices
    A = (int **)malloc(m * sizeof(int *));
    B = (int **)malloc(n * sizeof(int *));
    C = (int **)malloc(m * sizeof(int *));
    for (i = 0; i < m; i++) {
        A[i] = (int *)malloc(n * sizeof(int));
        C[i] = (int *)malloc(p * sizeof(int));
    }
    for (i = 0; i < n; i++) {
        B[i] = (int *)malloc(p * sizeof(int));
    }

    // Initialisation des matrices A et B (exemple d'initialisation arbitraire)
    for (i = 0; i < m; i++) {
        for (j = 0; j < n; j++) {
            A[i][j] = i + j;
        }
    }
    for (i = 0; i < n; i++) {
        for (j = 0; j < p; j++) {
            B[i][j] = i - j;
        }
    }

    // Calcul du produit
    matrixProduct(A, B, C, m, n, p);

    // Affichage du résultat
    printf("Matrice A :\n");
    for (i = 0; i < m; i++) {
        for (j = 0; j < n; j++) {
            printf("%d ", A[i][j]);
        }
        printf("\n");
    }

    printf("\nMatrice B :\n");
    for (i = 0; i < n; i++) {
        for (j = 0; j < p; j++) {
            printf("%d ", B[i][j]);
        }
        printf("\n");
    }

    printf("\nProduit de A et B :\n");
    for (i = 0; i < m; i++) {
        for (j = 0; j < p; j++) {
            printf("%d ", C[i][j]);
        }
        printf("\n");
    }

    // Libération de la mémoire allouée
    for (i = 0; i < m; i++) {
        free(A[i]);
        free(C[i]);
    }
    for (i = 0; i < n; i++) {
        free(B[i]);
    }
    free(A);
    free(B);
    free(C);

    return 0;
}
Affichage du Résultat

Modifiez votre programme pour afficher les matrices d’entrée et la matrice résultante du produit dans un format lisible à l’écran. Assurez-vous d’aligner correctement les éléments des matrices pour une meilleure lisibilité.

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

// Fonction pour calculer le produit de deux matrices rectangulaires
void matrixProduct(int **A, int **B, int **C, int m, int n, int p) {
    int i, j, k;

    // Parcourir les lignes de la première matrice
    for (i = 0; i < m; i++) {
        // Parcourir les colonnes de la deuxième matrice
        for (j = 0; j < p; j++) {
            // Initialiser l'élément (i, j) de la matrice résultante à 0
            C[i][j] = 0;
            // Parcourir les colonnes de la première matrice / les lignes de la deuxième matrice
            for (k = 0; k < n; k++) {
                // Calculer le produit et l'ajouter à l'élément (i, j) de la matrice résultante
                C[i][j] += A[i][k] * B[k][j];
            }
        }
    }
}

// Fonction pour afficher une matrice
void printMatrix(int **matrix, int rows, int cols) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            printf("%d ", matrix[i][j]);
        }
        printf("\n");
    }
}

int main() {
    int m = 2, n = 3, p = 2; // Tailles des matrices
    int **A, **B, **C;
    int i, j, k;

    // Allocation dynamique de mémoire pour les matrices
    A = (int **)malloc(m * sizeof(int *));
    B = (int **)malloc(n * sizeof(int *));
    C = (int **)malloc(m * sizeof(int *));
    for (i = 0; i < m; i++) {
        A[i] = (int *)malloc(n * sizeof(int));
        C[i] = (int *)malloc(p * sizeof(int));
    }
    for (i = 0; i < n; i++) {
        B[i] = (int *)malloc(p * sizeof(int));
    }

    // Initialisation des matrices A et B (exemple d'initialisation arbitraire)
    for (i = 0; i < m; i++) {
        for (j = 0; j < n; j++) {
            A[i][j] = i + j;
        }
    }
    for (i = 0; i < n; i++) {
        for (j = 0; j < p; j++) {
            B[i][j] = i - j;
        }
    }

    // Calcul du produit
    matrixProduct(A, B, C, m, n, p);

    // Affichage des matrices
    printf("Matrice A :\n");
    printMatrix(A, m, n);

    printf("\nMatrice B :\n");
    printMatrix(B, n, p);

    printf("\nProduit de A et B :\n");
    printMatrix(C, m, p);

    // Libération de la mémoire allouée
    for (i = 0; i < m; i++) {
        free(A[i]);
        free(C[i]);
    }
    for (i = 0; i < n; i++) {
        free(B[i]);
    }
    free(A);
    free(B);
    free(C);

    return 0;
}

Autres articles

Guide : Implémenter get_iemedans des fichiers avec...
La fonction get_iemepermet de récupérer le i-ème élément d'un fichier...
Read more
Guide : Implémenter un Fichier en Tableau...
Les fichiers en tableaux circulaires (ou files d'attente circulaires )...
Read more
Guide : Fichiers en Tableaux Circulaires en...
Les tableaux circulaires (ou buffers circulaires) sont des structures de...
Read more

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *