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 :

Créer une classe tableau


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    180
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 180
    Par défaut Créer une classe tableau
    Bonjour,

    Je m'entraine un peu au c++, et je dois définir une classe tableau qui vérifie les conditions suivantes :

    • On modélise un tableau de type T donné ( par exemple int )

    • Les objets de type T sont copiables par création et affectation

    • Les operateur operator [] (int i ) et operator [] (int i ) const retournent l'élément i du tableau. ( version const ou non )

    De plus la classe tableau doit contenir les champs suivant :
    • int n; // nombre de valeurs utilisées dans le vecteur

    • int nx; // nombre de valeurs allouées dans le vecteur ( n <=nx)

    • T*v; // un pointeur sur le tableau de valeurs allouées


    Avec un constructeur par défaut qui construit un tableau vide.

    Premièrement, je n'ai pas trop compris l'histoire des nx et n : mon tableau sera de taille nx et j'utiliserai n valeurs, c'est ça ? Je vois pas trop ce qu'ils veulent qu'on fasse ?

    Sinon pour le reste, j'ai fait ça :

    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
    typedef int T; // T de type int
    class tableau
    {
    public:
              tableau() {};   // tableau vide 
              tableau (int n1) { v= new T[n=n1];}       
              tableau( const tableau & source ){ // constructeur par copie
              n=source.n;
              nx=source.nx;
              // v=source.v;
              for(int i =0;i<n;i++) v[i]=source.v[i];                 
                       }
              int& operator[] (int i) { return v[i];} // & pour avoir création et affectation
              int& operator[] (int i) const { return v[i];}
    private:
               int n,nx;
               T*v;   
    };
    Pouvez-vous me dire si y'a des choses qui sont fausses ? Que l'on pourrait "mieux" écrire ?
    Je sais pas du tout si le tableau vide est correct.
    Je me demande aussi si je pouvais pas écrire :
    à la place de la boucle sur i ?

    Merci d'avance.

  2. #2
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Par défaut
    Non ça ne va pas.

    Alors déjà, ce qu'on a voulu te dire avec nx et n, c'est que nx représente la capacité totale de stockage de ton tableau (que tu donne visiblement dans le constructeur) tandis que n représente le nombre actuel d'éléments dans ton tableau (apparement on souhaite que tu gère les insertions d'éléments via une fonction Ajouter( T elem )).

    Tu vas devoir initialiser nx avec la taille max du tableau, allouer le tableau avec new et cette fameuse taille, et initialiser n à zero au début (on suppose qu'un tableau tout juste construit est d'office vide). Lorsque tu appelleras la méthode ajouter, tu devras comparer n et nx pour voir si il reste de la place dans ton tableau avant d'y stocker le bon element.

    Concernant ton constructeur par copie, tu ne peux pas écrire directement :
    car cela voudrait dire tout autre chose. Si tu veux t'affranchir de la boucle for, il existe dans la STL la fonction std::copy, il faut juste inclure <algorithm>.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    180
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 180
    Par défaut
    Merci Niamorh.

    lors déjà, ce qu'on a voulu te dire avec nx et n, c'est que nx représente la capacité totale de stockage de ton tableau (que tu donne visiblement dans le constructeur) tandis que n représente le nombre actuel d'éléments dans ton tableau (apparement on souhaite que tu gère les insertions d'éléments via une fonction Ajouter( T elem )).
    Tu vas devoir initialiser nx avec la taille max du tableau, allouer le tableau avec new et cette fameuse taille, et initialiser n à zero au début (on suppose qu'un tableau tout juste construit est d'office vide). Lorsque tu appelleras la méthode ajouter, tu devras comparer n et nx pour voir si il reste de la place dans ton tableau avant d'y stocker le bon element.
    En effet, après on doit créer une méthode qui permettra d'insérer des élements.
    Ok pour le nx et le n, mais donc mon constructeur va me donner :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    tableau (int n1) { v= new T[nx=n1];}
    Mais je vois pas où va intervenir le n dans ma classe ?
    Je rajoute simplement "n=0;" dans mon constructeur ?
    Et visiblement ça n'est qu'après que je l'utiliserais ( pour comparer avec nx) ...

  4. #4
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Par défaut
    Oui c'est ça.

    Par contre ça me fait vraiment mal de te voir apprendre le C++ avec le style jefaistouttenirsuruneseuleligne. Lorsque tu devras te relire, et pire, si quelqu'un d'autre doit te relire, c'est pas un cadeau que tu lui fera.
    Prends le temps d'écrire du code bien présenté, espace ton code, n'hésite pas à utiliser des variables temporaires dont tu choisiras un nom explicite (evite les notations hongroises style lpcstrMaChaine c'est très lourd pour rien), commente ton code, utilise les listes d'initialisation.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    tableau (int n1)
     : nx( n1 ),
       n ( 0 )
    {
      // Allocation de l'espace mémoire pour le tableau
      // Capacité : nx éléments
      v = new T[ nx ];
    }
    Citation Envoyé par rouliane Voir le message
    Mais je vois pas où va intervenir le n dans ma classe ?
    Je rajoute simplement "n=0;" dans mon constructeur ?
    Et visiblement ça n'est qu'après que je l'utiliserais ( pour comparer avec nx) ...
    Oui, il va beaucoup te servir en fait :
    Tu as pour le moment un tableau dont la mémoire a juste été réservée, les valeurs ne sont pas initialisées.

    Que se passe-t-il si tu accèdes aux éléments maintenant via l'opérateur[] ? Et bien tu vas lire ce qui se trouve dans la mémoire non initialisée, c'est à dire les valeurs qui s'y trouvaient au moment de ta demande d'allocation.
    Il faut que tu teste, avant de renvoyer la valeur, si l'index du tableau est valide ou non. Il est valide si il est positif ET inférieur au nombre d'éléments présents dans ton tableau, c'est à dire n. Pour t'assurer que l'index demandé est positif, tu peux imposer le passage d'un size_t à la place d'un int car size_t est non signé. Comme ça tu n'as plus qu'à faire le test si ( i < n ), si ce n'est pas vrai, tu lance une exception std::out_of_range.

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    180
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 180
    Par défaut
    Disons que mon prof fait tout tenir sur une seule ligne souvent donc je prend de mauvaises habitudes. Mais je vais faire attention.

    Je vais essayer de faire ce que tu me dis conçernant l'index du tableau ( je peux mettre aussi une ligne du style assert( i>=0 et i<=nx); je crois )

    Par contre, y'a quelque chose qui me chagrine avec l'opérateur [] justement.
    Par exemple je déclare b un tableau :

    je vais donc avoir un tableau de 2 éléments.
    Mais je me demandais donc ce que ça faisait si j'écrivais b[10]=5.
    Et là j'ai aucun problème à la compilation b[10] est bien affectée à 5 : mais comment cette valeur existe-t-elle alors que la commande b(2) a alloué un tableau de 2 entiers ??

  6. #6
    Membre expérimenté
    Profil pro
    Dev
    Inscrit en
    Décembre 2007
    Messages
    191
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations professionnelles :
    Activité : Dev

    Informations forums :
    Inscription : Décembre 2007
    Messages : 191
    Par défaut
    Bonjour,

    J'aimerai te redire ce que NiamorH a écrit d'une autre manière, peut être que cela t'éclairera les idées, et tu comprendras que finalement, ça ne cause pas de problème tordus à résoudre, les choses devraient t'apparaitre plus simplement.

    Répondons à la question : Pourquoi séparer la taille du vecteur en pratique (= son nombre d'éléments), et le nombre maximum de places possibles ?

    En effet ça pourrait etre plus simple de dire : si le tableau doit grossir, alors on réalloue la mémoire pile poil sur ce qu'il faut, et c'est tout :

    Il y aurait donc juste un seul n (pas de nx), qui est à la fois la taille allouée en mémoire et la taille du tableau rempli.

    Quand on ajoute un élément, on augment la taille de 1. Et donc fatalement lorsqu'on ajoute un élément il faut réallouer un tableau entier avec new et une copie (cette fois avec une valeur plus grande de 1 élément).

    Pareil quand on supprime, on devra réallouer en mémoire avec new et une copie un nouveau tableau de taille juste plus petite de 1 élément.


    Le problème avec cette méthode, ce sont toutes ces rallocations mémoire. Trouver de la place pour un tableau n'est pas chose complètement simple pour la système : les tableaux de base en C/C++ sont continus en mémoire : si le tableau a une taille de 20 alors il faut trouver une place assez grande pour stocker tous les éléments à la suite.


    Mais par exemple, si le système a accordé cette place, mais que tu ajoutes ne serait-ce qu'un élément : il va falloir réallouer la mémoire, et rien ne te promet que ce sera au meme endroit ! Il y a peut etre deja qqchose utilisé par le système après les 20 places. Donc le système va trouver l'allocation peut être ailleurs et donc tu devras également recopier tout le tableau original dans la nouvelle place allouée.

    Et ensuite, si tu veux réajouter un élément, meme problème, a priori il va falloir recopier encore tout le tableau dans une nouvelle place à 22 éléments.

    Sans parler que pour etre cohérent il faut aussi réallouer de la place (plus petite) quand on supprime un élément (alors qu'il n'y en as pas besoin).

    Donc imagine si ton tableau fait 10000 élément : il faudra recopier 10000 éléments pour en ajouter 1 : ce n'est pas efficace.



    Voila pourquoi on sépare : au début, à la création, on alloue une grosse place (nx==100 par exemple) avec un new. Mais en fait le tableau ne contient rien (n==0). Puis on le remplit en ajoutant des éléments (et n==1, puis n==2, puis n==3 ...), mais pas besoin d'allocation mémoire car le new a deja été fait. Alors bien sur, beaucoup de place est "gachée" ainsi ! Mais on peut se permettre d'avoir cette marge, car elle nous économise énormément d'opérations mémoires (les réallocations, copie)

    Au bout d'un moment quand meme, si on veut ajouter un élément alors que le tableau est plein (c'est a dire si n == 100 dans mon exemple), alors a ce moment la, on doit évidemment réallouer de la mémoire pour avoir la place de mettre les éléments suivants. (ou alors ta classe peut aussi l'interdire, demandant de réallouer assez de place avant de façon explicite)



    Donc résumons : maintenant ajouter un élément fait ceci : vérifier que le tableau n'est pas plein (que n <= nx) : Si c'est bon on ajoute simplement l'élément a la suite des autres et on incrémente n (pour se souvenir de combien d'éléments on a mis en vrai), sinon, il faut réallouer assez de place (donc augmenter nx) avant, ou alors simplement renvoyer une errreur par exemple.

    (C'est en fait exactement ce qui se passe dans le std::vector de la bibliotheque de modèles standards du C++, le tableau qu'on utilise habituellement pour pas mal de choses simples).


    EDIT : pfff j'ai écrit un paté et y'a eu des réponses entre temps, mes excuses, c'est deja résolu la question apparemment

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    180
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 180
    Par défaut
    Merci pacorabanix, c'est très clair !
    Je vais essayer de faire ça ( je dois en fait créer une méthode push_back pour ajouter un élément si n==nx )

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    180
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 180
    Par défaut
    Je remonte ce post , parce que je comprends toujours pas mon problème avec l'opérateur [].
    Même en créant un tableau 'tab' de 2 entiers, je peux accéder à l'élément tab[10]
    Merci

Discussions similaires

  1. Réponses: 14
    Dernier message: 28/02/2007, 09h53
  2. Réponses: 1
    Dernier message: 09/02/2007, 12h28
  3. [debutant] créer une constante tableau
    Par Emcy dans le forum C
    Réponses: 86
    Dernier message: 22/09/2006, 08h39
  4. Créer une classe commune à +sieurs fiches
    Par rtg57 dans le forum C++Builder
    Réponses: 2
    Dernier message: 08/05/2006, 17h58
  5. Réponses: 4
    Dernier message: 08/10/2005, 09h31

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