Partage
  • Partager sur Facebook
  • Partager sur Twitter

cout << "Problème";

Ou point non expliqué dans le tuto

Sujet résolu
    1 juillet 2007 à 18:34:53

    Salut,
    J'ai essayé de faire une classe String pour manipuler les chaînes de caractère. En fait, j'ai plutôt eu envie de refaire à la main la classe string. Tout marche bien, sauf une petite chose.. Voyez ce code:

    int main(int argc, char *argv[])
    {
            String chaine1 = "Du debut";
            String chaine2;
            chaine2 = " a la fin";
           
            cout << chaine1 << endl; // Marche
            cout << (chaine1+chaine2).getChaine() << endl; // Marche
            cout << chaine1 + chaine2 << endl; // Marche pas

      return EXIT_SUCCESS;
    }


    getChaine() me fais un simple affichage de la chaîne de type char* contenu dans mon objet de type String. Ce problème me semble général et ne s'applique pas qu'à mon code. En effet, dans le tutoriel sur la durée, si on essaie :

    Duree temps1(...); // Simplifié, me souviens plus l'assignation exacte
    Duree temps2(...);
    cout << temps1 << endl; // Marche
    cout << temps1 + temps2 << endl; // Marche pas
     


    Allons bon, pourtant temps1.operator+(temps2) est bien un objet de type Duree, cependant ça foire dans le cout, tout comme mon code. Reste-t-il une facette non expliquée dans la fonction qui se sert de operator<< ? Il y a bien un moyen puisqu'avec des objets de type string simple c'est possible, mais peut-être ont-il un meilleur accès au code de la bibliothèque iostream..
    • Partager sur Facebook
    • Partager sur Twitter
      1 juillet 2007 à 18:55:55

      Hello

      Montre nous voir le prototype de ton opérateur + et de ton opérateur <<.

      • Partager sur Facebook
      • Partager sur Twitter
      Co-auteur du cours de C++. ||| Posez vos questions sur le forum ||| Me contacter.
        1 juillet 2007 à 19:44:57

        D'accord, mais tu peux aussi prendre pour exemple le cours sur l'objet Duree puisque c'est le même problème.

        Voila une partie de c_string.h (les prototypes demandés)
        String& operator=(const String &originale);
        String operator+(const String &chaine);

        Et maintenant dans c_string.cpp
        String& String::operator=(const String &originale)
        {
                delete[] m_chaine;
                m_chaine = new char[sizeof(originale)];
                strcpy(m_chaine, originale.m_chaine);
                return *this;
        }

        String String::operator+(const String &chaine)
        {
                char* combo = m_chaine;
                strcpy(combo + strlen(combo), chaine.m_chaine);
                String renvoi(combo);
                return renvoi;
        }


        Mais même avec des codes tout simple il y a ce problème. Avez-vous déja réussi à rendre possible un "cout << objet1 + objet2;" ?
        • Partager sur Facebook
        • Partager sur Twitter
          1 juillet 2007 à 19:51:34

          Citation : SpotZup

          Mais même avec des codes tout simple il y a ce problème. Avez-vous déja réussi à rendre possible un "cout << objet1 + objet2;" ?


          faut mettre des parenthèses autour de l'addition sinon çà addition "cout" avec "objet2".
          utilises ceci :
          cout << (objet1 + objet2);
          • Partager sur Facebook
          • Partager sur Twitter
            1 juillet 2007 à 19:54:12

            Définis "ne marche pas". Problème de compilation ou d'exécution ?
            Je n'ai aucun problème avec ça (au pire s'il s'agit d'un problème de priorités, rajoutes des parenthèses):
            #include <iostream>

            struct T {
                int i_;
                T(int i) : i_(i) {}
                T operator-(T rhs) const { // écriture déconseillée
                    return T(i_ - rhs.i_);
                }
                T& operator+=(T rhs) { // écriture conseillée (1/2)
                    i_ += rhs.i_;
                    return *this;
                }
            };
            T operator+(T lhs, T rhs) { // écriture conseillée (2/2)
                return T(lhs)+=rhs;
            }

            std::ostream& operator<<(std::ostream & os, T v) {
                return os << v.i_;
            }

            int main (int argc, char **argv)
            {
                T t1(1);
                T t2(2);

                std::cout << t1 << std::endl;
                std::cout << t1+t2 << std::endl;
                std::cout << t2-t1 << std::endl;

                return 0;
            }


            PS: ton opérateur d'affectation n'est pas bon: il ne faut JAMAIS faire de delete avant de faire l'allocation de la nouvelle chaine. Solution juste dans la FAQ C++ de developpez

            PPS: ton opérateur d'affectation n'est pas bon (bis): sizeof() ne fais pas ce que tu crois. Il envoie la taille de ton objet, pas celle de ta chaine (pour laquelle il ne faudrait pas ublier le 0 terminal).

            PPPS: Ton opérateur de concaténation n'est pas bon (et compliqué): la quantité de mémoire utilisée est insuffisante. Ce qui me fait dire que tu as une erreur d'exécution.
            • Partager sur Facebook
            • Partager sur Twitter
            C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
              1 juillet 2007 à 20:41:12

              minirop: Non les parenthèses n'y changent rien j'avais essayé, l'opérateur + est prioritaire je crois apparemment.

              lmghs: Quand je dis "Marche pas", c'est lors de.. la compilation ? Bien que je soit pas sûr de bien différencier les deux. J'botiens le message suivant :
              erreur: no match for "operator<<" in "std::cout << chaine1. String::operator+(((const String&)((const String*)(& chaine2))))"
              J'ai corrigé tous les PS, mais le problème est toujours là.. Voila la nouvelle version de mes méthodes:

              String& String::operator=(const String &originale)
              {
                      char* temp = new char[strlen(originale.m_chaine)];
                      strcpy(temp, originale.m_chaine);
                      m_chaine = temp;
                      return *this;
              }

              String String::operator+(const String &chaine)
              {
                      char* combo = new char[strlen(m_chaine) + strlen(chaine.m_chaine)];
                      strcpy(combo, m_chaine);
                      strcat(combo, chaine.m_chaine);
                      String renvoi(combo);
                      return renvoi;
              }
               


              Et sinon lmghs, je redécouvre les structures dans ton exemple, mais est-ce sûr qu'en faisant plutôt une classe ça ne pose pas plus de problèmes ? Je suppose bien spur que non, mais quand on a une erreur faut se méfier de tout !
              • Partager sur Facebook
              • Partager sur Twitter
                2 juillet 2007 à 0:01:33

                Ton opérateur + (membre ; mauvaise pratique) devrait être const.

                Tu as effectivement une erreur de compilation. Et comment dire, je ne vois pas le rapport entre le message d'erreur et le code que tu nous montres.

                Tu as toujours des erreurs de gestion de la mémoire. (a- sizeof n'est pas ton ami ici pour =() ; b- attention au 0-terminal dans +() ; c- je soupçonne fortement une fuite de mémoire dans +(), dans =() il y en a une, c'est certain). Je te renvoie de nouveau à la FAQ que tu n'es visiblement pas allé lire.

                "class" et "struct" c'est pareil à un petit détail de visibilité près. Sans impact sur ton problème.
                • Partager sur Facebook
                • Partager sur Twitter
                C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
                Anonyme
                  2 juillet 2007 à 11:47:27

                  Est-ce possible de voir ton opérateur << ? J'ai beau éplucher le post, je ne l'ai toujours pas vu...
                  • Partager sur Facebook
                  • Partager sur Twitter
                    2 juillet 2007 à 12:32:38

                    lmghs:
                    a) Je n'utilise plus sizeof(), il me semble qu'on fait lorsqu'on écrit new type[x], le x doit valoir le nombre de trucs de ce type, c'est pour ça que j'utilise strlen.
                    b) Qu'est-ce que le 0-terminal ?
                    c) En effet ça se mélange un peu dans ma tête la gestion de la mémoire. J'aimerai savoir si ce raisonement est valide: En fait je considère ma variable m_chaine comme un pointeur vers une chaîne de caractère plutot que comme une chaîne (ce qui se déclare de la même façon). Ainsi, dans mon opérateur+() par exemple, je fais de la place en mémoire pointée par "temp" grâce a la fonction new, puis je dis que le pointeur m_chaine vaut temp, c'est à dire que m_chaine pointe vers la nouvelle place mémoire allouée. Tout ce que je dis est surement confus, mais pas autant que ça l'est dans ma tête.

                    Edit: je m'en vais de ce pas lire cette FAQ, pour être en forme avant les résultats du Bac.

                    Cyprien_ :
                    ostream &operator<<(ostream &out, String &chaine)
                    {
                            chaine.getChaine(out); // méthode qui fait out << m_chaine;
                            return out;
                    }

                    Il est tout bête. Mais je répète une nouvelle fois que vous pouvez simplement modifier le tuto sur les durées afin de rendre possible l'assignation multiple. Si vous désirez étudier l'ensemble de mes sources, je les ai hébergées à cette adresse.
                    • Partager sur Facebook
                    • Partager sur Twitter
                      3 juillet 2007 à 0:39:38

                      Quand tu suis des tutos ou des cours, la const-correction peut paraitre gadget. Seulement c'est quelque chose de très important. Tout particulièrement quand tu pars sur la surcharge d'opérateurs et que tu renvoies des choses par valeur. Pour accepter ces choses dans des fonctions, il est nécessaire que ces fonctions soient capables de recevoir des temporaires non nommés.
                      Pour cela, il n'y a pas 36 solutions, il n'y en a que deux et seulement deux. Tu devras recevoir des copies (innefficace sur des gros objets comme ici), ou des références constantes.

                      => Corrige ton opérateur d'injection. (il est pas impossible que cela t'oblige à rajouter les autres const qui de toutes façons font défaut).


                      Concernant tes autres questions.

                      a- je n'ai pas compris ta phrase.

                      b- En C, les chaines de caractères doivent être terminées par un caractère interprété comme drapeau de fin de chaine: le caractère 0 (=='\0'). Du coup, les chaines occupent toujours un octet de plus que leur longueur afin de stocker de drapeau de fin de chaîne.

                      c- Il y a des solutions très simples. On en avait discuté avec Cyprien_. Je t'invite à retrouver ces discussions qui remontent aux deux premières pages de ce forum.
                      Pour la concaténation, il est intéressant de décomposer ce problème complexe en sous-problèmes simples.
                      (*) +() s'implémente comme le retour de la copie du l'opérande gauche auquel on ajoute l'opérande droit (cf mon code plus haut)
                      (*) +=() s'implémente comme 1- s'il n'y a pas assez de place on se redimensionne, 2- on ajoute le membre droit à l'objet courant
                      (*) le resize() s'implémente comme une copie dans une zone surdimensionnée de l'objet courant, enchainée par un swap entre ce temporaire surdimensionné et l'objet courant. Cela nécessite de distinguer longueur et capacité. Autre situation : si on réduit la taille de l'objet.
                      • Partager sur Facebook
                      • Partager sur Twitter
                      C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
                        3 juillet 2007 à 19:10:28

                        Génial, j'ai enfin résolu mon problème ! lmghs, j'apprécie vraiment vos réponses parce tout ce vocabulaire nouveau et ces phrases compliquées pour un débutant permettent de comprendre de plus en plus de trucs ! ^^ J'ai donc corrigé la constance pour l'opérateur+, mais aussi et surtout celle pour l'opérateur d'injection. Voila sa nouvelle version:

                        ostream &operator<<(ostream &out, const String &chaine)
                        {
                                String temp(chaine);
                                temp.getChaine(out);
                                return out;
                        }

                        Bien que je comprenne l'utilité du mot clé "const", ce qui me trouble c'est sa nécessité. Je suppose que je dois me documenter sur la "const-correction" pour mieux comprendre. En tout cas M@téo21 a donc fait une erreur dans son tutoriel vu qu'il n'applique pas cette constance pour la fonction servant à l'opérateur d'injection.
                        Merci !
                        • Partager sur Facebook
                        • Partager sur Twitter
                          3 juillet 2007 à 22:00:27

                          Eh Eh. Je sais bien, c'est pas toujours évident de me suivre :-° . Mais disons que le gars motivé pourra apprendre et faire des recherches vu que j'essaie tant bien que mal d'utiliser le vocabulaire officiel, ou à défaut celui qui est le plus répandu pour exprimer un concept précis.

                          const est nécessaire parce qu'il veut dire (dans le contexte des paramètres de fonctions) "je te promets de ne pas modifier le paramètre que tu me files". Et vu qu'il est innacceptable de modifier un objet temporaire qui n'a pas de nom -- d'autant que : "quel intérêt ?", le modifier ne servirait à rien -- le langage interdit aux temporaires non nommés d'être acceptés comme paramètre réel pour un paramètre formel de type référence.

                          Il faut se rabattre vers les références constantes. Je ne serais pas étonné que cela soit traité dans la FAQ C++ de developpez ou une autre. De sûr quelques items du GOTW en parlent.


                          Bien que trop souvent négligé (d'autant plus quand on vient du C), "const" est vraiment très important en C++. On peut très bien coder 99% sans d'un logiciel et puis d'un coup (comme là) en avoir besoin. Ce qui a pour conséquence de devoir modifier plus de 25% des signatures du projet. Autant prendre l'habitude dès le début de s'en servir partout.
                          • Partager sur Facebook
                          • Partager sur Twitter
                          C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.

                          cout << "Problème";

                          × 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