IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Pointeur et scanf dans un tableau à 2 dimensions créé dynamiquement


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2012
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2012
    Messages : 9
    Par défaut Pointeur et scanf dans un tableau à 2 dimensions créé dynamiquement
    Bonjour,

    Je n'arrive pas à entrer des valeurs entières (par la fonction scanf dans la fonction donnees_tab du code suivant) dans un tableau à deux dimensions créé dynamiquement (erreur de segmentation).
    Je n'arrive pas à voir qu'est-ce qui colle.
    Par soucis de pédagogie (exercice destiné à des élèves de 1ere année de fac d'info), la manipulation des données lues et entrées se fait uniquement par pointeur.
    Merci à vous.

    Voici une partie du code:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    #include <stdio.h>
    #include <stdlib.h>
    #define TAILLE 10
     
    //Fonction d'initialisation de tableau a deux dimensions
    void initialisation_tab(int **, int **, int *, int *);
    //Fonction d'allocation memoire pour tableau
    void allocation(int **, int **, int *, int *,int);
    //Fonction de saisie des éléments d'un tableau
    void donnees_tab(int **,int **, int *, int *);
    //Fonction affichant les éléments d'un tableau
    void affichage(int **,int **, int **, int **,int *, int *, int);
     
    int main()
    {
        int nb_ligne,nb_colonne;
        int **tab=NULL, **p1=NULL,**p2=NULL,**tab2=NULL;
        int trans=0,mat=0;
     
        initialisation_tab(tab,p1,&nb_ligne,&nb_colonne);
     
        allocation(tab,p1,&nb_ligne,&nb_colonne,mat);
     
        mat=1;
        //création d'un tableau
        allocation(tab2,p2,&nb_ligne,&nb_colonne,mat);
     
        donnees_tab(tab,p1,&nb_ligne,&nb_colonne);
     
        printf("\nAffichage avant inversion : \n");
     
        affichage(tab,p1,tab2,p1,&nb_ligne,&nb_colonne,trans);
     
     
        free(tab);
        free(tab2);
     
        return 0;
    }
    void initialisation_tab(int **tab, int **p1, int *nb_ligne, int *nb_colonne)
    {
        do
        {
           printf("Veuillez entrer le nombre de ligne du tableau a 2 dimensions (maximum : %d) : ",TAILLE);
           scanf("%d",nb_ligne);
        }while((*nb_ligne<1)||(*nb_ligne>TAILLE));
     
        do
        {
           printf("Veuillez entrer le nombre de colonne du tableau a 2 dimensions (maximum : %d) : ",TAILLE);
           scanf("%d",nb_colonne);
        }while((*nb_colonne<1)||(*nb_colonne>TAILLE));
     
     
    }
     
    void allocation(int **tab, int **p1, int *nb_ligne, int *nb_colonne,int mat)
    {
        int i, **tab2=NULL;
        int nb_ligne_tmp, nb_colonne_tmp;
     
        if(mat==1)
        {
            nb_ligne_tmp=*nb_ligne;
            nb_colonne_tmp=*nb_colonne;
            tab2=tab;
            *nb_ligne=TAILLE;
            *nb_colonne=TAILLE;
        }
     
        tab=(int **)malloc(*nb_ligne*sizeof(int *));
     
        for(i=0; i<*nb_ligne; i++)
       {
           tab[i]=(int *)malloc(*nb_colonne*sizeof(int));
            if ( tab == NULL)
            {
                exit(0);
            }
       }
     
       *nb_ligne=nb_ligne_tmp;
       *nb_colonne=nb_colonne_tmp;
    }
     
     
    void donnees_tab(int **tab,int **p1, int *nb_ligne, int *nb_colonne)
    {
        int i,j;
        p1=tab;
     
        printf("\nvaleur de nb_ligne=%d et de nb_colonne=%d\n",*nb_ligne,*nb_colonne);
        for(i=0; i<(*nb_ligne); i++)
        {
            for(j=0; j<(*nb_colonne); j++)
            {
                printf("Veuillez entrez la valeur de l\'entier dans l\'emplacement tab[%d][%d] : ",i,j);
                fflush(stdin);
                scanf("%d",*(p1+i)+j);
            }
        }
     
    }
     
    void affichage(int **tab,int **p1, int **tab2, int **p2, int *nb_ligne, int *nb_colonne,int trans)
    {
        int i,j,aux;
        p1=tab;
     
        if(trans==1)
        {
            aux=*nb_ligne;
            *nb_ligne=*nb_colonne;
            *nb_colonne=aux;
            p1=tab2;
        }
     
        for(i=0; i<*nb_ligne; i++)
        {
            for(j=0; j<*nb_colonne; j++)
            {
                printf("%3d",*(*(p1+i)+j));
            }
        printf("\n");
        }
    }

  2. #2
    Membre chevronné

    Profil pro
    Inscrit en
    Août 2007
    Messages
    179
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 179
    Par défaut
    Bonjour,
    Citation Envoyé par info-pmc Voir le message
    Par soucis de pédagogie (exercice destiné à des élèves de 1ere année de fac d'info), la manipulation des données lues et entrées se fait uniquement par pointeur.
    ah, je sais pas si c'est très pédagogique de mettre des pointeurs partout. Surtout pour des valeurs qui ne doivent pas être modifiées.

    Juste 2 petites remarques pour commencer :

    Dans la fonction "allocation", tu fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
       *nb_ligne=nb_ligne_tmp;
       *nb_colonne=nb_colonne_tmp;
    alors que "nb_ligne_tmp" et "nb_colonne_tmp" n'ont été initialisées que si "if(mat==1)", du coup tu te retrouves avec des valeurs délirantes dès le premier appel (puisque mat=0)

    Ca ça n'a aucune chance de marcher.

  3. #3
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Ca ça n'a aucune chance de marcher.
    Et pourquoi donc ?

    Par contre,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        free(tab);
        free(tab2);
    ne libère pas toute la mémoire allouée et laisse une grosse fuite mémoire.

    Fuite également dans la fonction d'allocation si on a une erreur d'allocation sur tab[i]

    a un comportement dépendant de l'implémentation. fflush() ne doit être utilisé que sur les flux de sortie (voir FAQ C sur ce site).

  4. #4
    Membre chevronné

    Profil pro
    Inscrit en
    Août 2007
    Messages
    179
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 179
    Par défaut
    Citation Envoyé par diogene Voir le message
    Et pourquoi donc ?
    euh, j'avais mal lu, désolé..

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2012
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2012
    Messages : 9
    Par défaut
    Par contre,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        free(tab);
        free(tab2);
    ne libère pas toute la mémoire allouée et laisse une grosse fuite mémoire.
    En effet, pour chaque tableau à 2 dimensions, je dois d'abord libérer la mémoire (les colonnes) dans une boucle for, puis libérer les lignes par un simple free comme ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    // Liberation de la memoire
    for (i = 0; i < k; i++)
    {
    free(tab[i]);
    }
    free(tab);
    Fuite également dans la fonction d'allocation si on a une erreur d'allocation sur tab[i]
    Je ne comprends pas trop où je dois agir.

    a un comportement dépendant de l'implémentation. fflush() ne doit être utilisé que sur les flux de sortie (voir FAQ C sur ce site).
    =>Merci pour la remarque.

    Malgrè ces corrections, voilà ce que j'obtiens sous GDB

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    valeur de nb_ligne=2 et de nb_colonne=2
     
    Program received signal SIGSEGV, Segmentation fault.
    0x0000000000400b27 in donnees_tab (tab=0x0, p1=0x0, nb_ligne=2, nb_colonne=2)
    at mem-code.c:96
    96	           scanf("%d",*(p1+i)+j);
    (gdb)

  6. #6
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2012
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2012
    Messages : 9
    Par défaut
    Je viens de supprimer la fonction allocation.
    J'ai placé les 2 tableaux à 2 dimensions dans la fonction principale "main()". J'obtiens plus de fuite mémoire sans comprendre pourquoi ?

  7. #7
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    - Allocation() alloue mais met l'adresse obtenue dans la variable locale tab et la variable tab de main() reste inchangée à NULL. Du coup, donnees_tab() plante parce que tab et p1 sont à NULL.

    - pourquoi passer à initialisation_tab() les paramètres tab et p1 inutilisés ? void initialisation_tab(int *nb_ligne, int *nb_colonne);suffit.

    - pourquoi passer à allocation() le paramètre p1 inutilisé ? Le paramètre tab doit être l'adresse de destination pour pouvoir renvoyer l'adresse obtenue par les allocations : void allocation(int ***tab, int *nb_ligne, int *nb_colonne,int mat);et l'appel doit être
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    int main()
    {
        int nb_ligne,nb_colonne;
        int **tab=NULL;
        ...
        initialisation_tab(&nb_ligne,&nb_colonne);
        allocation(&tab,&nb_ligne,&nb_colonne,mat);
    ....
    ce qui donne pour la fonction d'allocation quelque chose comme (code non testé):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    void allocation(int ***tab, int *nb_ligne, int *nb_colonne,int mat)
    {
        int i,j ;
        if(mat==1)
        {
            *nb_ligne=TAILLE;
            *nb_colonne=TAILLE;
        }
        *tab=malloc(*nb_ligne*sizeof(int *));
        if(*tab != NULL)
        {
           for(i=0; i<*nb_ligne; i++)
           {
               (*tab)[i]=malloc(*nb_colonne*sizeof(int));
                if ((*tab)[i] == NULL)
                {
                    for(j=0; j<i; j++) free((*tab)[j]);
                    free(*tab);
                    *tab = NULL;
                    return;
                }
            }
       }
    }
    - Le paramètre p1 est également inutile dans donnees_tab(), c'est une variable locale ordinaire. Il n'y a aucune raison de passer les adresses du nombre de lignes et de colonnes plutôt que les valeurs elles-mêmes : void donnees_tab(int **tab, int nb_ligne, int nb_colonne); C'est un exercice sur les pointeurs, mais encore faut-il les utiliser à bon escient.

    - Dans la fonction affichage, le paramètre p2 ne sert à rien. Les raisons de passer les adresses du nombre de lignes et de colonnes plutôt que les valeurs elles-mêmes sont obscures pour moi; il est vrai que je ne comprend pas vraiment l'utilité et le rôle qu'on veut faire jouer aux paramètres tab2 et trans

    J'ai placé les 2 tableaux à 2 dimensions dans la fonction principale "main()". J'obtiens plus de fuite mémoire sans comprendre pourquoi ?
    Si tu ne montres pas le code utilisé, personne ne peut répondre.

Discussions similaires

  1. Problème pointeur dans un tableau à deux dimensions.
    Par Hunken dans le forum Débuter
    Réponses: 2
    Dernier message: 12/03/2015, 11h32
  2. Rechercher dans un tableau deux dimensions
    Par angelevil dans le forum VB 6 et antérieur
    Réponses: 4
    Dernier message: 28/09/2006, 20h29
  3. Réponses: 3
    Dernier message: 26/05/2006, 19h49
  4. 2 valeurs distincts dans un tableau à 2 dimensions...
    Par toyyo dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 23/08/2005, 16h00
  5. tri alphabétique dans un tableau deux dimensions
    Par *!!cocco!!* dans le forum Algorithmes et structures de données
    Réponses: 7
    Dernier message: 06/12/2004, 21h38

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo