Partage
  • Partager sur Facebook
  • Partager sur Twitter

C'est pas possible de retourner un tableau en c++

Sujet résolu
    11 avril 2019 à 16:47:43

    Pourquoi ai-je ce message d'erreur ci-dessous quand je veux retourner mon tableau ?

    Cannot initialize return object of type 'double' with an lvalue of type 'double [nombreNote]'

    Où ai-je péché ?

    double enregistreNote(unsigned int nombreNote)
    {
        double note[nombreNote];
        
        double somme(0);
        for (int i(0); i < nombreNote; ++i) {
            std::cout << "Entrez votre note " << i << " : ";
            std::cin >> note[i];
        }
        
        return note;
    }
    Merci pour l'assistance.
    • Partager sur Facebook
    • Partager sur Twitter
      11 avril 2019 à 16:51:04

      Code non valide en C++ "standard", les VLA n'ont jamais fait partie de la norme.

      Les VLA vont disparaitre de la norme C, donc oubliez cette cochonnerie de VLA.

      En C++, utilisez la classe std::vector et ça fonctionnera tout seul.

      • Partager sur Facebook
      • Partager sur Twitter
      Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
        13 avril 2019 à 16:22:12

        Salut, il faut, tout simplement faire attention à ce que l'on décide que la fonction va renvoyer

        Lorsque tu définis une fonction sous la forme de

        double enregistreNote(/* paramètres */)

        tu indiques au compilateur que cette fonction va renvoyer... un seul double...

        Or, un tableau de double, c'est, dans le pire des cas -- comprends ;  si on regarde la manière dont les éléments sont gérés au niveau de l'ordinateur -- un ensemble d'éléments (des doubles, dans le cas présents) qui sont contigus en mémoire, auxquels on peut accéder au travers de l'adresse à laquelle se trouve le premier élément du tableau, sur laquelle on va appliquer un "décalage" équivalent à la taille que le nombre d'éléments à "passer" prend en mémoire.

        Comme bacelar l'a si bien dit, l'idéal sera d'utiliser std::vector<> qui s'occupera de gérer la mémoire allouée au tableau de manière automatique, et donc de travailler sous une forme qui pourrait être proche de

        /* le fait de transmettre le tableau sous forme de référence
         * nous permet de faire en sorte que toutes les modifications
         * appliquées à tab au sein de la fonction soient répercutées
         * dans le tableau transmis comme argument
         */
        void enregistrerNote(std::vector<double> & tab,
                             double toAdd){
            tab.push_back(toAdd);
        } 

        Et, si tu tiens vraiment à faire les choses "comme tu les aurais faites en C" (ce qui n'est vraiment pas la meilleure idée que tu puisse avoir) il faudrait travailler sous une forme qui serait proche de

        /* comme une fonciton ne peut renvoyer qu'une seule valeur,
         * mais que nous voudrons modifier deux éléments (le pointeur 
         * sur le premier élément du tableau ET la taille du tableau ), nous transmettons la taille sous forme de référence
         */
        double * ajouterNote(double * tab, // le tableau
                             size_t & size, // la taille du tableau
                             double toAdd){
            /* on alloue assez de mémoire pour contenir un double
             * en plus que la taille actuelle du tableau
             */
            double * temp = new double[size +1];
            /* tout ce qui suit ne devra avoir lieu que si 
             * le tableau d'origine existe déjà
             */
            if(tab){
                /* on copie le contenu du tableau actuel dans le tableau
                 * temporaire
                 */
                memcpy(temp, tab, sizeof(double)+size);
                /* on ajoute la nouvelle note */
                temp[size] = toAdd;
                /* on libère la mémoire allouée au tableau d'origine */
                delete[] tab;
            }
                /* on incrémente la taille du tableau */
            ++size;
            /* on renvoie le pointeur sur le nouveau tableau */
            return temp;
        }
        /* le tout sera utilisé sous une forme proche de */
        int main(){
            size_t size{0}; // on commence avec un tableau vide
            double * tab{nullptr}; // idem
            double note = demanderNote(); // SRP inside : il faut
                                          // une fonction à part pour
                                          // questionner l'utilisateur
            ajouterNote(tab, size, note); // on ajoute la note
            /* ... */
            delete [] tab; // on n'oublie pas de libérer la mémoire
                           // quand on a fini
            return 0;
        }

        NOTE : je déconseille très fortement cette approche, car elle occasionne une quantité phénoménale de problèmes (ne serait-ce que parce qu'il y a, depuis C++11, des pointeurs intelligents qui pourraient nous venir en aide) dont les débutants n'ont clairement pas le recul suffisant pour en prendre conscience, et dont les développeurs avancés ont tellement conscience qu'ils préféreront les éviter.

        D'ailleurs, c'est bien simple : malgré le fait que ce code est presque correct en apparence, il est fondamentalement buggé, parce que la fonction demanderNote (dont le code n'est pas fourni ici) va -- de toute évidence -- provoquer une écriture sur la sortie standard (std::cout) ainsi qu'une lecture sur l'entrée standard (std::cin).  Or, la lecture et l'écriture peuvent échouer en lançant une exception, ce qui mettrait tout le reste de la logique à mal :'(

        Au pire, nous devrions décider de travailler avec des std::unique_ptr, ce qui impliquerait en code encore différent pour ajouterNote, qui prendrait alors une forme proche de

        void ajouterNote(std::unique_ptr<double>& tab, // le tableau
                             size_t & size, // la taille du tableau
                             double toAdd){
            /* je ne vais pas montrer le code ici */
        }
        /* qui sera utilisée sous une forme proche de */
        int main(){
            std::unique_ptr<double> tab{nullptr};
            size_t size;
            double note=demanderNote();
            ajouterNote(tab, size, note);
            /* ... */
            return 0;
        }

        Mais, comme std::vector est spécialement conçu pour s'occuper de la représentation de la notion de tableaux, il serait particulièrement dommage de se priver de son utilisation ;)

        • Partager sur Facebook
        • Partager sur Twitter
        Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
          14 avril 2019 à 14:53:19

          Merci pour les éclaircissements. En effet, je suis à mon tout début avec le C++.
          • Partager sur Facebook
          • Partager sur Twitter

          C'est pas possible de retourner un tableau en c++

          × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
          × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
          • Editeur
          • Markdown