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

Langage C++ Discussion :

[Langage] Probleme avec les tableaux dynamiques


Sujet :

Langage C++

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    34
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 34
    Points : 31
    Points
    31
    Par défaut [Langage] Probleme avec les tableaux dynamiques
    Bonjours tout le monde!


    Voila je butte sur ca: le programme compile mais il bloque à l'execution, ca fait 2h que j'essaye de omprendre pourquoi...Le probleme c'est que je sais que quand qulqu'un va me dire la solution je vais avoir l'air tout con mais bon comme c'est préssé comme projet: (aperemment c la commande affichage qui fait planter)


    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
     
    void AffichageBuffer(short **test,int TailleSignal){
         int i,j;
     
          for (i=0;i<10;i++){
                           for (j=0;j<TailleSignal/2;j++){
                               cout<<test[i][j]<<endl;
                               }
     
                         }
                         }
     
     
     
    void InitialiseBuffer(short **buffer1,short **buffer2,int TailleSignal){
     
         int i,j;
     
         buffer1=new short *[10];
         buffer2=new short *[10];
     
                     for (i=0;i<10;i++){
                         buffer1[i]=new short [TailleSignal/2];
                         buffer2[i]=new short [TailleSignal/2];}
         for (i=0;i<10;i++){
                           for (j=0;j<TailleSignal/2;j++){
                               buffer1[i][j]=0;
                               buffer2[i][j]=0;}
     
                         }
                         }
     
     
    int main(int argc, char *argv[])
    {
        int LaTailleSignal,i,j;
        short ** bufferD, **bufferG;
        short *ATraiter;
     
        LaTailleSignal=10;
     
     
    InitialiseBuffer(bufferD,bufferG,LaTailleSignal);    
     
    AffichageBuffer(bufferD,LaTailleSignal);
     
        system("PAUSE");
        return EXIT_SUCCESS;
     
     
     
    }

  2. #2
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 629
    Points : 30 692
    Points
    30 692
    Par défaut
    Salut, et bienvenue sur le forum...

    Le code que tu nous présente est quelque part l'exemple type de la mécompréhension du principe des pointeurs...

    Ne t'en fais pas, nous sommes tous passés par là un jour ou l'autre: il ne faut donc pas y voir une quelconque attaque personnelle

    Le fait est que, si tu veux que bufferD et bufferG soient bien modifiés par la fonction InitialiseBuffer, tu dois, à "la mode C", passer... l'adresse de ces deux variable, et donc en arriver à travailler avec... des pointeurs de pointeurs de pointeurs ou..., à la "mode C++", une référence sur un pointeur de pointeur

    Pour que tu puisse comprendre le principe, il faut passer par la compréhension de ce qu'est un pointeur.

    Pour faire simple, et donc, fatalement de manière "pas forcément complète", un pointeur est une variable qui contient... l'adresse à laquelle on trouvera l'objet réel.

    Cela signifie que, à la base, un pointeur de pointeur devrait contenir (une fois qu'il a été initialisé)... l'adresse à laquelle on trouvera... l'adresse sur un élément du type visé.

    Il faut aussi comprendre que, quel que soit le type que tu passe en argument à une fonction du genre de:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void foo(Type arg)
    {
        /* ce que l'on fait n'importe pas */
    }
    tu travailles avec... une copie de la variable qui sera passée lors de l'appel.

    aussi, lorsque tu en arrive à un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void foo(Type** arg)
    {
    }
    void bar()
    {
        Type** var;
        foo(var);
    }
    foo utilise... une copie du pointeur de pointeur qui se nommait var dans bar.

    Cela implique que cette copie sera détruite lorsque l'on arrivera à la fin de la fonction foo, et que... var ne subit aucune modification dans dans bar.

    Pour palier cela, il faut trouver un moyen de faire de manière à ce que var soit effectivement modifié.

    Il existe deux moyens de le faire: soit passer (à la "mode C++") une référence (un alias) de la variable comme paramètre, soit passer l'adresse à laquelle la variable se trouve (à la "mode C").

    Pour un type quelconque, cela signifie que foo deviendrait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    /* à la mode C++ */
    void foo(Type & arg);
    /* OU --- OU --- OU à la mode C */
    void foo(Type* arg);
    et que l'appel se ferait sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void bar()
    {
        Type var;
        /* A la mode C++ */
        foo(var);
        /* OU --- OU --- OU à la mode C */
        foo(&var);
    }
    Si donc on adapte cela au fait que la variable est à la base un pointeur de pointeur, le prototype de foo devient
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    /* à la mode C++ */
    void foo(Type **& arg);
    /* OU --- OU --- OU à la mode C */
    void foo(Type*** arg);
    et les appels se font sous les formes de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    void bar()
    {
        /*aucun changement mis à part le fait que var est un pointeur de pointeur
         */
        Type** var;
        /* A la mode C++ */
        foo(var);
        /* OU --- OU --- OU à la mode C */
        foo(&var);
    }
    [EDIT]Après la théorie, je ne peux m'empecher de signaler qu'une matrice n'est, en définitive qu'un tableau contenant X*Y éléments, et qu'il est souvent plus simple d'envisager les choses sous cet angle

    De plus, il existe une classe qui présente tous les avantages du tableau dynamique, mais qui te permet d'en éviter tous les inconvénients (tout ce qui est lié à la gestion dynamique de la mémoire): la classe vector fournie par le standard dans l'espace de noms std et accessible par simple inclusion du fichier d'en-tête <vector>...

    Une petite recherche sur le forum ou sur internet devrait t'en apprendre plus (mais tu peux toujours demander )

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    34
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 34
    Points : 31
    Points
    31
    Par défaut
    MERCI
    Je ne sais pas pkoi dans ma tete je pensais qu'il ne fasais pas de copie de pointeurs... c'est vrai que j'avais l'habitude de le faire pour des trucs du genre
    int a;
    fo(&int)

    mais je croyais que vu que les tableaux c t déjà des adresses...


    En ce qui concerne la classe vector...j'apprenderai a l'utiliser plus tard...C'est pas vraiment ma priorité d'avoir un code propre mais plutot rapide (traitement temps réel de signal) et donc je fais mon petit tabealu une seule fois et après je remplis je remplis je traite...Maintenant que je sais faire le tableau...PASSONS AUX choses serieuses
    Merci encore: y'a rien de plus chiant que de rester coincé et tu m'a fais une réponse qui m'a expliquée mon erreur: en pointeur apermment fo toujours en qulque sorte travailler un niveau au dessus

  4. #4
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 381
    Points : 41 582
    Points
    41 582
    Par défaut
    Citation Envoyé par wawa84 Voir le message
    mais je croyais que vu que les tableaux c t déjà des adresses...
    Un tableau est implicitement convertible en l'adresse de son premier élément et est toujours transmis comme tel, mais ça n'a rien à voir avec ton code, où tu es déjà en train de manipuler des pointeurs.

    De plus, même avec un paramètre de type tableau, tu ne peux modifier le tableau lui-même, seulement les éléments qu'il contient.

  5. #5
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 629
    Points : 30 692
    Points
    30 692
    Par défaut
    Citation Envoyé par wawa84 Voir le message
    <snip>
    mais je croyais que vu que les tableaux c t déjà des adresses...
    <TROLL>il faut laisser croire les béguines, elle sont spécialistes et payée pour </TROLL>
    Beaucoup plus sérieusement:

    C'est effectivement tout le problème des tableaux "C style".

    Effectivement, lorsque tu déclare une variable sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    foo()
    {
        Type tab[N];
    }
    la variable tab contient, effectivement, l'adresse à laquelle se trouve le premier élément du tableau, ou, plutot, est implicitement transformable en un pointeur sur le premier élément du tableau.

    Mais, dans le code que tu présente, tu ne travaille pas avec un tableau
    Tu aurais travaillé avec un tableau si tu avais déclaré les variables bufferD et bufferG sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    float bufferD[X][Y];
    float bufferG[X][Y];
    mais tu n'aurais alors pas pu gérer les éléments de manière dynamique, et ton problème aurait été différent: avoir la certitude que, quoi qu'il arrive, il te sera possible de placer suffisemment d'éléments dans les matrice, tout en veillant à ne pas "perdre inutilement" trop de mémoire

    Dans le code que tu présente, tu travailles, de manière explicite, avec des pointeurs de pointeurs.

    Le fait que, par la suite, tu utilise ces pointeurs de pointeurs comme un tableau à deux dimensions n'est - pour ainsi dire - qu'un détail d'implémentation

    Mais donc, ta variable est de type... float**, et, si tu arrive à concevoir que les deux étoiles "vont de pair" avec float, tu en arrive à comprendre la raison pour laquelle il faut passer une référence ou un pointeur sur cette variable pour pouvoir la modifier

  6. #6
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 381
    Points : 41 582
    Points
    41 582
    Par défaut
    En C++, je conseille d'utiliser le passage par référence.
    Mais quand tu bosses "à la C", je conseille de passer par des structures pour plus de clarté:
    Code C : 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
    #include <stdlib.h>
    #include <stdio.h>
     
    struct tableauSimpleShort
    {
    	short *pElems;
    };
     
    struct tableauDoubleShort
    {
    	struct tableauSimpleShort * pTableauxSimples;
    };
     
    short * NewShorts(size_t n)
    {
    	short *pRet = malloc(n * sizeof *pRet);
    	return pRet;
    }
    struct tableauSimpleShort * NewTableauxSimplesShort(size_t n)
    {
    	struct tableauSimpleShort *pRet = malloc(n * sizeof *pRet);
    	return pRet;
    }
     
    void InitialiseBufferSimple(struct tableauSimpleShort *pBufferSimple, int TailleSignal) {
    	size_t const cElemsSimple = TailleSignal/2;
    	size_t j;
     
    	pBufferSimple->pElems = NewShorts(cElemSimple);
     
    	for (j=0 ; j<cElemsSimple ; j++) {
    		pBufferSimple->pElems[i] = 0;
    	}
    }
     
    void InitialiseBufferDouble(struct tableauDoubleShort *pBufferDouble, int TailleSignal) {
     
    	size_t const cElemsDouble = 10;
    	size_t i;
     
    	pBufferDouble->pTableauxSimples = NewTableauxSimplesShort(cElemsDouble);
     
    	for (i=0 ; i<cElemsDouble ; i++) {
    		InitialiseBufferSimple( &(pBufferDouble->pTableauxSimples[i]), TailleSignal );
    	}
    }
     
    void InitialiseBuffers(struct tableauDoubleShort *pBuffer1, struct tableauDoubleShort *pBuffer2, int TailleSignal)
    {
    	InitialiseBufferDouble(pBuffer1, TailleSignal);
    	InitialiseBufferDouble(pBuffer2, TailleSignal);
    }
     
    void AffichageBuffer(struct tableauDoubleShort const *pcTest, int TailleSignal) {
     
    	size_t const cElemsSimple = TailleSignal/2;
    	size_t const cElemsDouble = 10;
    	size_t i;
     
    	for(i=0 ; i<cElemsDouble ; i++) {
    		size_t j;
    		for (j=0 ; j<cElemsSimple ; j++) {
    			short affich = pcTest->pTableauxSimples[i].pElems[j];
    			printf("%d\n", affich);
    		}
    	}
    }
     
    int main(int argc, char *argv[])
    {
    	int LaTailleSignal;
    	struct tableauDoubleShort bufferD, bufferG;
     
    	/*short *ATraiter;*/
    	LaTailleSignal=10;
     
    	InitialiseBuffer(&bufferD, &bufferG, LaTailleSignal);    
     
    	AffichageBuffer(&bufferD, LaTailleSignal);
     
    	system("PAUSE");
    	return EXIT_SUCCESS;
    }
    Encore que, après réglexion, je ne suis pas sûr que ce soit si clair que ça...

  7. #7
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 629
    Points : 30 692
    Points
    30 692
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    En C++, je conseille d'utiliser le passage par référence.
    Mais quand tu bosses "à la C", je conseille de passer par des structures pour plus de clarté:
    Code C : 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
    #include <stdlib.h>
    #include <stdio.h>
     
    struct tableauSimpleShort
    {
    	short *pElems;
    };
     
    struct tableauDoubleShort
    {
    	struct tableauSimpleShort * pTableauxSimples;
    };
     
    short * NewShorts(size_t n)
    {
    	short *pRet = malloc(n * sizeof *pRet);
    	return pRet;
    }
    struct tableauSimpleShort * NewTableauxSimplesShort(size_t n)
    {
    	struct tableauSimpleShort *pRet = malloc(n * sizeof *pRet);
    	return pRet;
    }
     
    void InitialiseBufferSimple(struct tableauSimpleShort *pBufferSimple, int TailleSignal) {
    	size_t const cElemsSimple = TailleSignal/2;
    	size_t j;
     
    	pBufferSimple->pElems = NewShorts(cElemSimple);
     
    	for (j=0 ; j<cElemsSimple ; j++) {
    		pBufferSimple->pElems[i] = 0;
    	}
    }
     
    void InitialiseBufferDouble(struct tableauDoubleShort *pBufferDouble, int TailleSignal) {
     
    	size_t const cElemsDouble = 10;
    	size_t i;
     
    	pBufferDouble->pTableauxSimples = NewTableauxSimplesShort(cElemsDouble);
     
    	for (i=0 ; i<cElemsDouble ; i++) {
    		InitialiseBufferSimple( &(pBufferDouble->pTableauxSimples[i]), TailleSignal );
    	}
    }
     
    void InitialiseBuffers(struct tableauDoubleShort *pBuffer1, struct tableauDoubleShort *pBuffer2, int TailleSignal)
    {
    	InitialiseBufferDouble(pBuffer1, TailleSignal);
    	InitialiseBufferDouble(pBuffer2, TailleSignal);
    }
     
    void AffichageBuffer(struct tableauDoubleShort const *pcTest, int TailleSignal) {
     
    	size_t const cElemsSimple = TailleSignal/2;
    	size_t const cElemsDouble = 10;
    	size_t i;
     
    	for(i=0 ; i<cElemsDouble ; i++) {
    		size_t j;
    		for (j=0 ; j<cElemsSimple ; j++) {
    			short affich = pcTest->pTableauxSimples[i].pElems[j];
    			printf("%d\n", affich);
    		}
    	}
    }
     
    int main(int argc, char *argv[])
    {
    	int LaTailleSignal;
    	struct tableauDoubleShort bufferD, bufferG;
     
    	/*short *ATraiter;*/
    	LaTailleSignal=10;
     
    	InitialiseBuffer(&bufferD, &bufferG, LaTailleSignal);    
     
    	AffichageBuffer(&bufferD, LaTailleSignal);
     
    	system("PAUSE");
    	return EXIT_SUCCESS;
    }
    Encore que, après réglexion, je ne suis pas sûr que ce soit si clair que ça...
    on peut effectivement se poser la question... deux structures et 4 fonctions rien que pour gérer une matrice 2D (et bien que cela permette par la meme occasion de gérer un tableau simple)... une chance que l'on ne souhaite pas en avoir une 4D

    De plus, je n'ai malgré tout pas oublié que nous sommes sur le forum C++...

    C'est la raison pour laquelle je parlais en priorité de l'utilisation des références, et, si j'ai parlé d'une version avec pointeurs, ce n'était que pour être complet

  8. #8
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    34
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 34
    Points : 31
    Points
    31
    Par défaut
    merci!

    Je suis en C++ donc je suis passé en refernece... tout a l'aire de bien fonctionner[pour l'insatant]

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. probleme avec les tableaux
    Par heeedi dans le forum Débuter avec Java
    Réponses: 2
    Dernier message: 22/05/2009, 10h17
  2. Panique avec les Tableaux dynamiques
    Par Swiper dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 27/06/2007, 15h52
  3. Réponses: 12
    Dernier message: 17/12/2006, 11h46
  4. Réponses: 12
    Dernier message: 30/07/2004, 15h43
  5. [langage] probleme avec les listes dans des listes
    Par pqmoltonel dans le forum Langage
    Réponses: 7
    Dernier message: 27/04/2004, 12h32

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