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 :

Erreur de concaténation


Sujet :

C++

  1. #1
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2012
    Messages : 39
    Points : 16
    Points
    16
    Par défaut Erreur de concaténation
    Bonsoir,

    Je suis actuellement étudiant en deuxième année de BTS IG, et j'ai un soucis sur un de mes programmes concernant la concaténation. Je m'explique : Mon but est d'afficher un tableau en console (assez basique en soit), et de rajouter une tabulation en fonction du nombre de lettre du nom entré.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    void afficherMenu (double prixMenu[],string nomMenu[])
    {
           for (int i=0;i<numMenuMax;i++)
           {
               string txt = i + ") Menu : " + nomMenu[i] + "\t";
               if (nomMenu[i].length()<=4) {txt += "\t";}
               txt += "Prix : " + prixMenu[i] + "\n";
               cout << txt;
           }
    }
    Comme je l'ai dis, c'est assez basique en soit, pourquoi le compilateur refuse d'effectuer sa tache, en me disant :
    "invalid operands of types `const char[8]' and `double' to binary `operator+' "
    Je ne comprends pas pourquoi il ne veut pas insérer mon double dans mon tableau de string. J'ai essayer de convertir, mais ma tentative a été vaine.

    Merci d'avance pour toute réponse que je recevrais, et bonne soirée!

  2. #2
    Membre habitué Avatar de Xtrem_Voyageur
    Homme Profil pro
    Inscrit en
    Juin 2009
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2009
    Messages : 85
    Points : 154
    Points
    154
    Par défaut
    Plusieurs choses à dire.

    Déjà, je n'aime pas trop cette façon de passer un tableau en paramètre. Je ne vais pas entrer dans des considérations techniques mais saches qu'un tableau quoiqu'il arrive n'est jamais passé par valeur, c'est impossible, cela signifie que le tableau passé en argument ne sera jamais copié dans l'argument formel utilisé comme paramètre de ta fonction. En gros, le nom du tableau est toujours converti implicitement en pointeur et est passé comme tel, du coup inutile de mettre en argument
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    void afficherMenu (double prixMenu[],string nomMenu[])
    cela suffira :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    void afficherMenu (double *prixMenu, string *nomMenu)
    En général, on passe également la taille des tableaux en paramètre vu qu'il n'y aucun moyen de la connaitre, mais tu sembles avoir défini la taille comme une variable constante fixée par avance.

    Maintenant les tableaux eux-mêmes, le C++ est doté d'une librairie relativement facile d'utilisation : la STL qui permet d'utiliser des conteneurs tout prêt.
    Au lieu d'utiliser des tableaux, utilises donc vector
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    std::vector<double> vd;
    std::vector<string> vs;
    tu pourras comme cela modifier le prototype de ta fonction en
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    void afficherMenu (const std::vector<double>& prixMenu, const std::vector<std::string>& nomMenu)
    et passer les arguments par référence, ce qui évitera des copies inutiles.

    Et pour ton erreur de concaténation, on ne concatène pas comme cela des types différents.
    D'ailleurs tu n'es pas obligé d'utiliser un string. Tu peux aussi utilisé 2 fois le flux de sortie cout.

  3. #3
    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
    Bonjour,

    Pour construire de telles chaînes de caractères, il te faut, avec la STL, passer par les flux std::ostringstream (cf F.A.Q.)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
          for (int i=0;i<numMenuMax;i++)
           {
              std::ostringstream oss;
              oss<<i<<") Menu : "<<nomMenu[i]<<"\t";
               if (nomMenu[i].length()<=4) {oss<<"\t";}
               oss<<"Prix : "<<prixMenu[i]<<"\n";
               cout << oss.str();
           }
    Ceci dit, s'il s'agit uniquement de le sortir sur la console, alors pas besoin de passer par le flux de chaîne de caractère mais autant utiliser directement std::cout :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
           for (int i=0;i<numMenuMax;i++)
           {
              std::cout<<i<<") Menu : "<<nomMenu[i]<<"\t";
               if (nomMenu[i].length()<=4) {std::cout<<"\t";}
               std::cout<<"Prix : "<<prixMenu[i]<<"\n";
           }

    Sinon, comme dit ci-dessus, les tableaux, en C++, c'est std::vector ou std::array (en C++11 ou avec boost) pour les tableaux de taille fixe. Ca évite d'avoir une horrible variable globale numMenuMax qui traîne dans ton code (les variables globales, c'est vraiment mal).

    Ceci-dit, je préfère souvent passer un couple d'itérateur à un tableau rendant les fonctions plus 'souples' vis à vis de la structure de donnée.
    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
    template <class iterator1, class iterator2>
    void afficherMenu (
       iterator1 prixMenuBegin,
       iterator1 prixMenuEnd,
       iterator2 nomMenuBegin
    )
    {
       int i=0;
       for (;prixMenuBegin!=prixMenuEnd;++prixMenuBegin,++nomMenuBegin,++i)
       {
          std::cout<<i<<") Menu : "<<*nomMenuBegin<<"\t";
          if ((*nomMenuBegin).length()<=4) {std::cout<<"\t";}
          std::cout<<"Prix : "<<*prixMenuBegin<<"\n";
       }
    }
    Et, là on se rend souvent compte que ca correspond déjà à un algorithme existant de la STL qui conjointement à l'utilisation des itérateurs de la STL permet de ne se concentrer que sur la fonction 'utile' - l'affichage du menu - et de laisser le reste à la STL :
    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
    std::string afficherItemMenu(double prix_,std::string nomMenu_)
    {
       std::stringstream oss;
       oss<<") Menu : "<<nomMenu_<<"\t";
       if (nomMenu_.length()<=4) {oss<<"\t";}
       oss<<"Prix : "<<prix_;
       return oss.str();
    }
     
    template <class iterator1, class iterator2>
    void afficherMenu (
       iterator1 prixMenuBegin,
       iterator1 prixMenuEnd,
       iterator2 nomMenuBegin
    )
    {
       std::transform(prixMenuBegin,prixMenuEnd,nomMenuBegin,std::ostream_iterator<std::string>(std::cout,"\n"),afficherItemMenu);
    }
    Encore 2 remarques,
    => les prix et les menus sont fortement liés. donc pourquoi ne pas les regrouper dans une structure commune (par exemple std::pair si pas besoin de plus, ou carrément une structure/classe si du comportement est nécessaire pour l'application).
    => Quand je vais au resto, je confesse que je paie rarement les centimes derrière le second chiffre après la virgule... En général, un prix à un nombre fixe de chiffre derrière la virgule. L'utilisation du type double est inapproprié. Pourquoi ne pas utiliser un type intégrale en considérant que le prix est stocké en centimes ?

    Au final, ca pourrait ressembler à ça (en C++11) :
    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
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    #include <iostream>
    #include <string>
    #include <iterator>
    #include <sstream>
    #include <algorithm>
    #include<utility>
    #include <locale>
     
    typedef std::pair<std::string,unsigned> menuDescription;
    std::string afficherItemMenu(menuDescription item_)
    {
       std::stringstream oss;
       oss<<") Menu : "<<item_.first<<"\t";
       if (item_.first.length()<=4) {oss<<"\t";}
       oss<<"Prix : "<<item_.second/100;
       if(item_.second%100)
       {
           const char decimal_point = std::use_facet<std::numpunct<char> >(oss.getloc()).decimal_point ();
           oss<<decimal_point<<item_.second%100;
       }
       oss<<" Euros";
       return oss.str();
    }
     
    int main()
    {
     
        std::vector<menuDescription> const Carte =
        {
            {"un",111}
            ,{"deux",222}
            ,{"trois",333}
            ,{"quatre",444}
            ,{"cinq",500}
        }; // en C++03, utiliser push_back Carte.push_back(menuDescription("six",600)); au détriment de la constance de Carte
        std::transform(std::begin(Carte),std::end(Carte),std::ostream_iterator<std::string>(std::cout,"\n"),afficherItemMenu);
        // en C++03, remplacer std::begin(Carte) par Carte.begin() et std::end(Carte) par Carte.end()
       return 0;
    }

  4. #4
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2012
    Messages : 39
    Points : 16
    Points
    16
    Par défaut
    Bonjour,

    Tout d'abord merci pour vos deux réponses.
    Je tiens d'abord à préciser que si mon code est loin d'être optimal, c'est que j'utilise uniquement mes acquis (c'est pas très pro en effet).

    T'as seconde solution est la réponse à mon problème 3DArchi, et je t'en remercie. Ce qui m'épate, c'est que c'était ma première idée, et que cela ne fonctionnait pas.
    Concernant les vector, je vais me pencher dessus.

    Merci beaucoup

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

Discussions similaires

  1. Réponses: 11
    Dernier message: 05/06/2007, 14h29
  2. Traitement de fichiers, erreur de concaténation
    Par moook dans le forum Langage
    Réponses: 4
    Dernier message: 24/04/2007, 10h09
  3. Erreur de concaténations dans un DATAMODULE
    Par hadid dans le forum Bases de données
    Réponses: 8
    Dernier message: 10/04/2007, 14h52
  4. Erreur de concaténation
    Par eclipse012 dans le forum Langage
    Réponses: 2
    Dernier message: 07/11/2006, 11h12
  5. Etat MsAccess : #erreur avec concaténation de champs
    Par pyxosledisciple dans le forum Access
    Réponses: 5
    Dernier message: 01/03/2006, 20h35

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