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 :

tableau de tableau


Sujet :

Langage C++

  1. #1
    Membre éprouvé
    Avatar de ChPr
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    2 090
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Val d'Oise (Île de France)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 090
    Points : 1 055
    Points
    1 055
    Par défaut tableau de tableau
    Bonjour à toutes et à tous,

    Je souhaite créer dynamiquement un tableau de tableaux d'entiers dont les deux dimensions sont des variables.

    Créer un tableau d'entiers c'est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    int nbPts; // nombre de points du tableau
    int *val; // pointeur sur le tableau d'entiers
    ...
    val = new int[nbPts]; // création dynamique du tableau
    Maintenant, je ne sais pas quoi écrire pour déclarer la construction dynamique de mon tableau de tableaux ; quel est le type du tableau de tableaux ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int nbTbl; // nombre de tableaux
    int nbPts; // nombre de points d'un tableau (même valeur pour tous les tableaux
    int *val; // pointeur sur le tableau d'entiers
    ...
    ??? // création dynamique des tableaux
    Merci de votre aide.

    Pierre.

  2. #2
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Hello,

    Tu peux utiliser un tableau à une dimension de taille x*y, et y accéder via une petite fonction style
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    int xyToInd(int x, int y) {
        return y*TAILLE_X + x;
    }
     
    int *tab = new int[TAILLE_X*TAILLE_Y];
    tab[xyToInd(2, 3)] = 42;
    Il est aussi possible d'avoir une classe gérant ton tableau et de surcharger l'opérateur() pour y accéder.

    (Ou la même chose en remplaçant par un vector si tu trouves un moyen de l'utiliser).

    Sinon la syntaxe pour avoir 2 "vraies" dimensions
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    int **tab = new int[TAILLE_Y];
    for(int i=0; i<TAILLE_Y; ++i) {
        tab[i] = new int[TAILLE_X];
    }
    // et pareil pour les delete
    for(int i=0; i<TAILLE_Y; ++i) {
        delete[] tab[i];
    }
    delete[] tab;

  3. #3
    Membre éprouvé
    Avatar de ChPr
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    2 090
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Val d'Oise (Île de France)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 090
    Points : 1 055
    Points
    1 055
    Par défaut
    Merci Iradrille pour cette réponse.

    La première solution est celle que j'aurais adoptée si je n'avais pas eu de réponse.

    Dans la deuxième solution, je pensais bien qu'il fallait créer le tableau de tableaux puis chaque tableau. mais je ne voyais pas comment. Cette notion de pointeur de pointeur, je n'y aurais jamais pensé.

    Cordialement.

    Pierre

  4. #4
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Citation Envoyé par ChPr Voir le message
    La première solution est celle que j'aurais adoptée si je n'avais pas eu de réponse.
    Et je te conseille de l'utiliser.
    En fonction de comment tu utilisera ton tableau, il peut être utile de réfléchir à mettre les cases d'une même ligne ou d'une même colonne côte à côte en mémoire.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    int xyToInd(int x, int y) {
        return y*TAILLE_X + x; // en ligne
    }
    int xyToInd(int x, int y) {
        return x*TAILLE_Y + y; // en colonne
    }
    Tu peux gagner beaucoup en performance en faisant le bon choix ici (ou perdre beaucoup, ça dépend comment on voit les choses )

  5. #5
    Membre éprouvé
    Avatar de ChPr
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    2 090
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Val d'Oise (Île de France)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 090
    Points : 1 055
    Points
    1 055
    Par défaut
    Bon, en fait, ce n'est pas résolu. Pour que cela compile, j'ai dû modifier ta proposition en :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    int TAILLE_X = 50;
    int TAILLE_Y = 2;
    int **tab;
     
    void init() {
      *tab = new int[TAILLE_Y];
      for(int i=0; i < TAILLE_Y; ++i) {
        tab[i] = new int[TAILLE_X];
      }
    }
    Ensuite, je ne dois pas savoir comment y accéder, je fais :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    tab[i][j] = x; // i = valeur de 0 TAILLE_Y-1 et j = valeur de 0 TAILLE_X-1 ; l'inverse n'est pas mieux
    int y = tab[i][j];
    je ne recueille pas en y la valeur x.

    Comment fait-on ?

    Merci de votre aide.

    Pierre

  6. #6
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par ChPr Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      *tab = new int[TAILLE_Y];
    Surtout pas malheureux ! On ne déférence jamais un pointeur non initialisé.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      tab = new int*[TAILLE_Y];
    Sinon tu pouvais aussi regarder la FAQ avant de poser ta question.
    Évite aussi au maximum l'emploi de variables globales. Privilégie le passage en paramètre.

  7. #7
    Membre éprouvé
    Avatar de ChPr
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    2 090
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Val d'Oise (Île de France)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 090
    Points : 1 055
    Points
    1 055
    Par défaut
    Merci Winjerome pour cette correction : ça fonctionne bien.

    Pour autant, j'ai recopié bêtement ce que tu m'as dit sans absolument rien n'y comprendre. J'avoue que cette histoire d'étoile m'ennuie vraiment. Quand on peut écrire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    iint a = 321;
    int *p = &a;
     
    void init() { 
      p = &a;
      *p = a;
    }
    • En ligne 2 et 5 c'est respectivement *p et p qui est égal à &a.
    • En ligne 2 et 6 c'est *p qui est respectivement égal à &a puis a.

    Faut avouer que ce n'est pas de la plus grande clarté pour un débutant. Alors, une étoile coincée entre un type de variable et un indicateur de taille ...

    Je vous remercie tous pour votre patience.

    Mais bon, je finirai bien pas comprendre.

    Cordialement.

    Pierre

  8. #8
    Invité
    Invité(e)
    Par défaut
    Attention à ne pas t'embrouiller l'esprit avec la déclaration du pointeur.
    Le * dans la ligne int *p = &a; est pour dire que p est de type int * : un pointeur sur int.
    On lui donne la valeur &a exactement comme dans la ligne p = &a;.

    Voit cette ligne comme Type nom = valeur; :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int *p = &a;
    // Type : int *
    // nom : p
    // valeur : &a
    Tout comme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int a = 321;
    // Type : int
    // nom : a
    // valeur : 321
    Maintenant pour revenir aux tableaux :
    int **tab; est un pointeur sur pointeur de int, autrement-dit tab a pour Type int **, et va contenir comme valeur l'adresse d'un int *.
    Dans notre cas, cette adresse sera la première d'un tableau de TAILLE_Y éléments de type int *.
    Tableau qui sera alloué avec cette ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      tab = new int*[TAILLE_Y];
    ligne que tu peux voir comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    nom = new TypeElements[nbElements];
    Tu te retrouves ainsi avec tab[0], tab[1], ... tab[TAILLE_Y-1] : chacun étant un pointeur sur int. Mais ceux-ci ne contiennent encore aucune adresse valide comme valeur, c'est ce que l'on va rectifier avec notre boucle :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for(int i=0; i < TAILLE_Y; ++i) {
        tab[i] = new int[TAILLE_X];
    chaque tab[i] va alors contenir l'adresse du premier élément d'un tableau nouvellement alloué de TAILLE_X int.
    Images attachées Images attachées  

  9. #9
    Membre éprouvé
    Avatar de ChPr
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    2 090
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Val d'Oise (Île de France)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 090
    Points : 1 055
    Points
    1 055
    Par défaut
    Je te remercie Winjerome pour les explications que tu te donnes le mal de me donner. Mais ce n'est pas peine perdue et je commence à y voir un peu plus clair.

    Ce qui m'a fichu un peu (beaucoup, je devrais dire) dedans, ce sont ces trois types d'écriture équivalents :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int* p
    int * p
    int *p
    où moi, j'ai plutôt attaché l'étoile à la variable alors qu'elle qualifie le type que la variable pointe. Ce qui explique ce que je ne comprenais pas : l'étoile coincée entre un type et un indicateur de taille.

    Mais je trouve que c'est quand même pernicieux quand cette même étoile, dans l'expression

    veut dire * p est la valeur de a. Mais bon, faut s'y faire.

    Cordialement.

    Pierre

  10. #10
    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 fait, le gros problème c'est que la syntaxe pour déclarer un pointeur ressemble à la syntaxe pour utiliser le pointeur, sans être identique.

    ----

    Sinon, quand tu as un tableau 2D dont tu ne prévois pas de changer la taille après la création, tu peux faire un truc un peu hybride entre le new int[TAILLE_X*TAILLE_Y] et le tableau de tableaux. En gros, un truc composé de:
    • Un tableau alloué avec new int[TAILLE_X*TAILLE_Y], où tu n'as pas à gérer de multiples allocations et désallocations en boucle
    • Un tableau de pointeurs sur int, permettant d'utiliser le tableau avec la syntaxe p[ligne][colonne].

    En combinant les deux, on obtient deux tableaux au lieu de N+1, tout en étant aussi facile d'emploi. Le résultat ressemble à ceci en mémoire.

    J'ai déjà fait un tel code, jette un œil à la fonction C++ Alloc2D (j'en ai aussi fait une version pour le C, appelée AutreAllocTable2D).

  11. #11
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    Et le problème encore plus gros, c'est la multiplicité des syntaxes :

    • int* variable est identique à int *variable
    • const int variable est équivalent int const variable ; alors quand on rajoute là-dessus des pointeurs...

  12. #12
    Membre éprouvé
    Avatar de ChPr
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    2 090
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Val d'Oise (Île de France)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 090
    Points : 1 055
    Points
    1 055
    Par défaut
    Citation Envoyé par oodini Voir le message
    Et le problème encore plus gros, c'est la multiplicité des syntaxes : ...
    Vive le Pascal objet ... Ok, je sors.

    Cordialement.

    Pierre

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

Discussions similaires

  1. [Tableaux] un tableau de tableau ??
    Par hitchie dans le forum Langage
    Réponses: 13
    Dernier message: 24/01/2006, 16h35
  2. Problème avec un tableau de tableau
    Par SubZero2 dans le forum Langage
    Réponses: 4
    Dernier message: 07/12/2005, 15h25
  3. [Tableaux] tableau de tableau
    Par Kerod dans le forum Langage
    Réponses: 4
    Dernier message: 26/11/2005, 19h30
  4. Réponses: 21
    Dernier message: 21/11/2005, 09h52
  5. [langage] Probleme de tri d'un tableau de tableau
    Par Ludo167 dans le forum Langage
    Réponses: 1
    Dernier message: 25/08/2004, 10h32

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