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 :

Allocation dynamique d'un tableau de pointeur


Sujet :

C++

  1. #1
    Membre actif Avatar de Général03
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    848
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2006
    Messages : 848
    Points : 283
    Points
    283
    Par défaut Allocation dynamique d'un tableau de pointeur
    Bonjour,

    je suis débutant en C++ et je bloque sur un point basique. Comment faire pour créer un tableau de pointeur où la taille de celui n'est pas précisé ?
    J'ai fait cela
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char *monTab[10] = {NULL} ;
    monTab[10] = new char ;
    mais j'aimerais vraiment le rendre dynamique, or ici je suis limité à 10 entrées.

    Merci
    Mes contributions phares en dev : www.rigaudie.fr

  2. #2
    Membre éclairé
    Avatar de Florian Goo
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    680
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2008
    Messages : 680
    Points : 858
    Points
    858
    Par défaut
    Bonsoir,

    Utilise std::vector !
    Les tableaux dynamiques, c'est du C, voire du vieux C++.
    Cours : Initiation à CMake
    Projet : Scalpel, bibliothèque d'analyse de code source C++ (développement en cours)
    Ce message a été tapé avec un clavier en disposition bépo.

  3. #3
    Invité
    Invité(e)
    Par défaut
    Normalement, tu ferais :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    char **tab=new char*[n];
    for(int i=0;i<n;i++)  tab[i]=new char[p];
    Mais comme le disait Florian, il vaut mieux faire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    vector<char*> tab(n);
    for(int i=0;i<n;i++)  tab[i]=new char[p];
    ou encore mieux

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    vector<string> tab(n);
    Comme ca tu n'as plus besoin d'allouer ou de désallouer...

    Francois

  4. #4
    Membre actif Avatar de Général03
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    848
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2006
    Messages : 848
    Points : 283
    Points
    283
    Par défaut
    Merci pour vos conseils. En faite, je ne souhaite pas utiliser la STL donc je vais opter pour
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char **tab=new char*[n];
    for(int i=0;i<n;i++)  tab[i]=new char[p];
    mais n et p sont des constantes que je dois initialisé ou pas ? J'avais déclaré comme cecimais j'obtiens toujours n=0 et p=3910792, c'est normal ?

    Merci
    Mes contributions phares en dev : www.rigaudie.fr

  5. #5
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Points : 4 732
    Points
    4 732
    Par défaut
    En faite, je ne souhaite pas utiliser la STL
    Raisons ?

    mais n et p sont des constantes que je dois initialisé ou pas ?
    Oui, sinon les valeurs sont indéterminées.
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  6. #6
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par Général03 Voir le message
    Merci pour vos conseils. En faite, je ne souhaite pas utiliser la STL donc je vais opter pour
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char **tab=new char*[n];
    for(int i=0;i<n;i++)  tab[i]=new char[p];
    Si ton tableau est alloué et désalloué d'un coup, une astuce à connaitre est d'allouer toutes les lignes en un seul bloc (tab[0]) et de placer les tab[i] derrière à la bonne distance...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    char **tab=new char*[n];
    tab[0]=new char[n*p];
    for(int i=1;i<n;i++) tab[i]=tab[i-1]+n;
    Ca gagne un peu de temps, et ca permet des opérations "malignes" sur les lignes du tableau (par exemple le parcours de tout le tableau en une boucle unique)

    Citation Envoyé par Général03 Voir le message
    mais n et p sont des constantes que je dois initialisé ou pas ? J'avais déclaré comme cecimais j'obtiens toujours n=0 et p=3910792, c'est normal ?
    Il n'y a pas de raison que ces valeurs soient toujours les mêmes... Ca va dépendre de ton environnement (et si par malheur n ou p est négatif...). Quoi qu'il en soit, tu ne peux allouer un tableau donc tu ne connais pas la taille...

    Francois

  7. #7
    Membre actif Avatar de Général03
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    848
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2006
    Messages : 848
    Points : 283
    Points
    283
    Par défaut
    Quoi qu'il en soit, tu ne peux allouer un tableau donc tu ne connais pas la taille...
    ben....en faite....c'est se que je cherche à faire !!! Il y a surement un moyen d'augmenter la taille de mon tableau si toutefois il est trop court à un certain endroit de mon programme ?
    Mes contributions phares en dev : www.rigaudie.fr

  8. #8
    Membre émérite

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Points : 2 252
    Points
    2 252
    Par défaut
    Ben, cf. la première réponse
    Citation Envoyé par Florian Goo
    Utilise std::vector !
    (qui redimensionne automatiquement son tableau interne quand on dépasse la capacité du vecteur, en allouant un nouveau tableau plus grand et en recopiant les précédents éléments)

  9. #9
    Membre actif Avatar de Général03
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    848
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2006
    Messages : 848
    Points : 283
    Points
    283
    Par défaut
    En faite quelle est la différence entre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char *monTab[10] = {NULL} ;
    monTab[10] = new char ;
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char *monTab ;
    monTab=new char[n];
    car dans mon code si je remplace ma 1er déclaration par la 2eme ça ne marche pas, alors qu'avec le 1er ça tourne nickel !! Pourtant si je comprend bien c'est la même chose sauf que n vaut un entier défini lors de la compilation, non ??
    Mes contributions phares en dev : www.rigaudie.fr

  10. #10
    Membre averti Avatar de Jenna
    Inscrit en
    Décembre 2009
    Messages
    272
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations forums :
    Inscription : Décembre 2009
    Messages : 272
    Points : 339
    Points
    339
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char *monTab[10] = {NULL} ;
    monTab[10] = new char ;
    C'est dansgereux cela car le dernier élément d'un tableau de 10 éléments, c'est l'indice 9, pas 10
    La valeur n'attend pas le nombre des années

  11. #11
    Membre actif Avatar de Général03
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    848
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2006
    Messages : 848
    Points : 283
    Points
    283
    Par défaut
    C'est dansgereux cela car le dernier élément d'un tableau de 10 éléments, c'est l'indice 9, pas 10
    Je suis d'accod avec toi mais si n vaut 10 (donc un tableau de 11 cases), les 2 déclarations précédentes sont identiques ?
    Mes contributions phares en dev : www.rigaudie.fr

  12. #12
    Membre averti Avatar de Jenna
    Inscrit en
    Décembre 2009
    Messages
    272
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations forums :
    Inscription : Décembre 2009
    Messages : 272
    Points : 339
    Points
    339
    Par défaut
    Citation Envoyé par Général03 Voir le message
    Je suis d'accod avec toi mais si n vaut 10 (donc un tableau de 11 cases), les 2 déclarations précédentes sont identiques ?
    Si n vaut 10, tu as 10 cases dont les indices vont de 0 à 9
    La valeur n'attend pas le nombre des années

  13. #13
    Membre actif Avatar de Général03
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    848
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2006
    Messages : 848
    Points : 283
    Points
    283
    Par défaut
    Si n vaut 10, tu as 10 cases dont les indices vont de 0 à 9
    Que dois je comprendre à cela puisque tu ne reponds pas à ma question ???
    Mes contributions phares en dev : www.rigaudie.fr

  14. #14
    Membre averti Avatar de Jenna
    Inscrit en
    Décembre 2009
    Messages
    272
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations forums :
    Inscription : Décembre 2009
    Messages : 272
    Points : 339
    Points
    339
    Par défaut
    Je ne cherchais pas forcément à répondre à ta question mais dans un bout de code que tu postes, il y a une faute et je tentais de te l'expliquer :

    sur un tableau de 10 éléments (char *monTab[10] = {NULL}; )

    tu n'as pas le droit d'utiliser l'élément dont l'indice est 10 car il est hors du tableau
    La valeur n'attend pas le nombre des années

  15. #15
    Membre confirmé Avatar de Lavock
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    560
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 560
    Points : 633
    Points
    633
    Par défaut
    Citation Envoyé par Général03 Voir le message
    Je suis d'accod avec toi mais si n vaut 10 (donc un tableau de 11 cases), les 2 déclarations précédentes sont identiques ?
    Ben, non... new char [10], c'est un équivalent, plus complexe, de malloc(sizeof(char) * 10)). Ca va te chercher un bloc mémoire contigu de 10 élément libre et te retourner l'adresse du premier.

    tab[10] = new char, ça cherche un octet de libre, et te retourne son adresse... pour essayer de l'écrire dans la 11 cellule d'un tableau qui n'en a que dix.

    La solution est soit utiliser vector, soit gérer ta mémoire tout seul à l'aide des fonctions C d'allocation mémoire.
    The mark of the immature man is that he wants to die nobly for a cause, while the mark of the mature man is that he wants to live humbly for one.
    --Wilhelm Stekel

  16. #16
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Général03 Voir le message
    En faite quelle est la différence entre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char *monTab[10] = {NULL} ;
    monTab[10] = new char ;
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char *monTab ;
    monTab=new char[n];
    car dans mon code si je remplace ma 1er déclaration par la 2eme ça ne marche pas, alors qu'avec le 1er ça tourne nickel !! Pourtant si je comprend bien c'est la même chose sauf que n vaut un entier défini lors de la compilation, non ??
    Outre que ce que dit Jenna est vrai - accéder à l'index 10 d'un tableau de 10 éléments te fait taper dans une zone mémoire non autorisée par ta déclaration (un beau dépassement ça s'appelle), les deux lignes sont assez différentes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char *monTab[10] = {NULL} ;
    Tu déclares un tableau de pointeurs de caractère contenant (le tableau) 10 entrées : monTab[0], monTab[1], ... monTab[9]. Ces entrées sont des pointeurs de char. = {NULL} permet d'initialiser ces 10 pointeurs à NULL.
    -> Le type de monTab est char** (je simplifie)
    -> Le type de monTab[i] est char*
    Ensuite :
    Tu alloues un caractère et tu places son adresse dans monTab[9], le dixième élément de ton tableau.

    Dans l'autre cas :
    Tu déclare un pointeur de monTab.
    Type de monTab = char *

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int n = 10;
    monTab=new char[n];
    Tu alloues n (ici 10) caractères consécutifs et tu places l'adresse dans monTab.
    -> Le type de monTab est char*
    -> Le type de monTab[i] est char

    Tu vois que ce sont deux choses différentes.

    Si tu souhaites ensuite 'agrandir' ton tableau, tu n'as pas d'autres choix que de réallouer un nouveau tableau de la taille voulue, de copier les anciennes valeurs vers ce nouveau tableau et de détruire l'ancien :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    // resize :
    Type *tableau;
    tableau = new Type[10];
    // maintenant j'en veux 20 :
    Type *new_tableau;
    new_tableau = new Type[20];
    for(int i=0;i<10;++i){
       new_tableau[i] = tableau[i];
    }
    delete []tableau;
    tableau = new tableau
    1/ Note que ce code n'est pas sûr : les exceptions ne sont pas gérées et tu peux te retrouver avec des pointeurs perdus.
    2/ Ce code suppose que Type a un constructeur par défaut
    3/ Ce code suppose que Type est copiable.

    Pourquoi recommande-t-on d'utiliser la STL, std::vector et std::string. Tout simplement parce que ces types encapsulent tous les problèmes relatifs à la gestion des données en brut et permettent de se concentrer sur des problèmes de haut niveau.
    Faut-il ne pas savoir gérer des pointeurs alors ? Non. Ce n'est pas la réponse. Mais quand on débute avec le C++, il est non seulement plus simple de commencer avec la STL, mais aussi ça permet d'apprendre les bonnes pratiques. L'apprentissage est facilitée. Les pointeurs, les tableaux dynamiques peuvent être abordés plus tard quand on commence à mieux maîtriser le langage. Et là, on se rend compte qu'il n'y a jamais de bonnes raisons d'utiliser de tels tableaux dynamiques construits à la main.

  17. #17
    Membre actif Avatar de Général03
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    848
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2006
    Messages : 848
    Points : 283
    Points
    283
    Par défaut
    La solution est soit utiliser vector, soit gérer ta mémoire tout seul à l'aide des fonctions C d'allocation mémoire.
    En faite je ne souhaite pas utiliser la STL, c'est pour cela que je souhaite gérer la memoire mais justement je bloque puisque quand j'utilise
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char *monTab ;
    monTab=new char[n];
    j'ai des erreurs qui n'apparaissait pas auparavant comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    error C2664: 'strlen' : impossible de convertir le paramètre 1 de 'char' en 'const char *'
    quand je fais cela
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    if(strlen(monTab[a]) == b)
    {
    ...
    }
    Mes contributions phares en dev : www.rigaudie.fr

  18. #18
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Cf ma réponse précédente sur la différence entre les 2...

  19. #19
    Membre actif Avatar de Général03
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    848
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2006
    Messages : 848
    Points : 283
    Points
    283
    Par défaut
    Merci 3DArchi pour tes explications claires, j'ai vu ton post qu'après avoir répondu...
    Faut-il ne pas savoir gérer des pointeurs alors ? Non. Ce n'est pas la réponse. Mais quand on débute avec le C++, il est non seulement plus simple de commencer avec la STL, mais aussi ça permet d'apprendre les bonnes pratiques. L'apprentissage est facilitée. Les pointeurs, les tableaux dynamiques peuvent être abordés plus tard quand on commence à mieux maîtriser le langage. Et là, on se rend compte qu'il n'y a jamais de bonnes raisons d'utiliser de tels tableaux dynamiques construits à la main.
    Je pensais qu'utiliser la gestion mémoire soi même était un bon moyen d'apprendre et de se familiariser avec les pointeurs. Je tente quand même ta proposition de rédéclaration.

    Merci
    Mes contributions phares en dev : www.rigaudie.fr

  20. #20
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Général03 Voir le message
    Je pensais qu'utiliser la gestion mémoire soi même était un bon moyen d'apprendre et de se familiariser avec les pointeurs.
    Que dirais-tu si à la première leçon pour le permis de conduire, le moniteur ouvre le capot, sort le moteur, le démonte, te donne une clé et te dis 'vas-y, c'est remonte-moi ça'. Tu as beau connaître le principe du moteur à explosion et tu as beau avoir envie de conduire, tu te rends compte qu'on ne prend pas la chose par le bon bout. Pour l'apprentissage du C++ c'est pareil. Vouloir débuter en attaquant les pointeurs et toutes leurs problématiques, n'est pas une bonne idée.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. allocation dynamique d'un tableau de pointeurs
    Par Dilettante dans le forum C++
    Réponses: 9
    Dernier message: 29/06/2007, 23h41
  2. Réponses: 2
    Dernier message: 05/03/2007, 18h37
  3. Réponses: 67
    Dernier message: 13/02/2007, 18h08
  4. Réponses: 13
    Dernier message: 01/10/2006, 00h25
  5. [PRO*C] Allocation dynamique d'un tableau de VARCHAR
    Par NéalZheimer dans le forum Interfaces de programmation
    Réponses: 5
    Dernier message: 07/07/2006, 13h02

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