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 :

Problème avec la methode c_str()


Sujet :

C++

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    82
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 82
    Points : 25
    Points
    25
    Par défaut Problème avec la methode c_str()
    Bonjour,

    comme c'est marqué dans le titre du topic, j'ai un problème avec la méthode c_str() de la classe std::string.
    Voici le contexte : je récupère des informations via un recv sur un socket, à chaque recv je met ce que j'ai reçu dans un char*, puis je rajoute cette chaîne à un std::string, jusqu'à que j'ai tout reçu.
    Quand je regarde la taille du contenu de mon std::string via la méthode length(), j'ai bien quelque chose de correcte, mais lorsque j'appelle c_str() pour vérifier le contenu, ça me retourne une chaine courte de 4 ou 5 caractères, toujours la même, qui serait je suppose une adresse.

    Merci d'avance pour l'aide que vous pourrez m'apporter.

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 071
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 071
    Points : 12 116
    Points
    12 116
    Par défaut
    n'y aurait-il pas des caractères non imprimables dans ta chaîne ?

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    82
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 82
    Points : 25
    Points
    25
    Par défaut
    Ce n'est pas ça le problème, le std::string contient bien la bonne chaine, je l'ai affiché et c'est nickel (y'a en moyenne plus de 35000 caractères dedans, voir bien plus), mais c_str() me renvoie une suite de quelques caractères (4 ou 5) et toujours les même. Je pensais à une adresse, mais c'est peu probable que ce soit exactement la même à chaque fois.

  4. #4
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    40
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Avril 2009
    Messages : 40
    Points : 33
    Points
    33
    Par défaut
    tu peux nous montrer comment tu fais stp? Moi je ferais plutôt un truc comme ca:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    size_t size = tonstring.size() + 1;
    char* chaine = new char[size];
    strncpy(chaine,tonstring.c_str(),size);

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    82
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 82
    Points : 25
    Points
    25
    Par défaut
    C'est bien beau grutt, mais dans ton exemple tu utilise la méthode c_str(), cette méthode même qui me pose problème.

    J'ai un char[1500] (1500 représentant la taille d'un packet), et lorsque je fais un recv, à chaque tour de boucle je rajoute dans mon std::string le contenu du char[1500], via la methode append() pour rajouter pile ce que j'ai reçu.

  6. #6
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    Effectivement, la fonction c_str() de la classe string renvoie... un pointeur sur le premier élément la chaine de caractères "C style" équivalente au contenu de la chaine

    Mais, ce que j'ai le plus de mal à comprendre, c'est dans quel but tu souhaites transformer cette chaine std::string en chaine "C style", alors qu'une bonne partie de ton travail a, justement, consisté à... créer une chaine std::string sur base de chaines "C styles" récupérées par ailleurs.

    Je ne veux certainement pas dire que tu ne dois pas le faire, mais je veux insister ici sur le fait que le seul cas "cohérent" dans lequel tu voudrais le faire est d'effectuer une analyse (sémantique ou syntaxique) de cette chaine ou de convertir la chaines en "autre chose" (ce qui revient quelque part à passer par une analyse de la chaine)...

    Et, dans ce cas, ce n'est, à mon sens, pas par une chaine "C style" qu'il et intéressant de passer, mais bien par... un flux de conversion stringstream (ou toute autre méthode de récupération de données sauvegardée)
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  7. #7
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    82
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 82
    Points : 25
    Points
    25
    Par défaut
    Je fais ça pour une raison bien sûr. J'utilise le framework Qt4, le std::string contient en fait une image jpeg que je dois passer en argument à la méthode loadFromData de la classe QImage, cette méthode demande un uchar (autrement dit un unsigned char*).
    Par ailleurs je viens de tester quelque chose et je trouve cela assez surprenant, lorsque j'utilise c_str() pour écrire dans un fichier (en faisant fichier.write(buffer.c_str(), buffer.length()) ), le contenu y est bien inscrit.

  8. #8
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Tu veux dire que ta std::string contient des données brutes, contenant potentiellement des octets nuls?
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  9. #9
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Je crains alors que l'utilisation de la classe string ne soit pas vraiment adaptée à ton problème...

    En effet, il faut se rappeler qu'une chaine de caractères est à considérer comme un tableau de caractères particulier:
    1. la chaine est considérée comme étant finie au premier caractères '\0' rencontré
    2. certains caractères ne sont pas affichables (en gors, tous ceux qui se trouvent aux indexes 0 à 31 inclus de la table ASCII)
    3. ...

    Or, une image jpeg est une image... compressée, qui doit donc être considérée comme une série de données binaires, et qui disqualifie de facto toute tentative de considérer ces données comme... de simples caractères "utilisables dans une chaine de caractères".

    Ce que tu devrais utiliser, c'est un système de "buffer", qui pourrait, pourquoi pas, consister en un vecteur de caractères, et qui pourrait (première proposition venue "à chaud", donc, forcément susceptible d'être améliorée) ressembler à
    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
     
    /* soit buff est le buffer récupéré par recv et
     * len est la taille du buffer en question
     */
     
    /* S'il n'y a qu'une seule récupération de données */
    std::vector<char> tab(&buff[0],&buff[0]+len);
    /* si tu dois "concaténer" plusieurs récupérations de données */
    std::vector<char> tab;
    while (recv(buff,len, flags)!=0)
    {
        tab.insert(tab.end(),&buff[0],&buff[0]+len);
    }
    /* pour récupérer le contenu réel sous la forme d'un char* */
    char* final=&tab[0];
    }
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  10. #10
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    À mon avis, std::string peut tout-à-fait marcher, mais il faut s'assurer que tout ce qui dépend de la longueur de la chaîne utilise std::string::length() et absolument pas strlen() ni un équivalent: length() retournera toujours la longueur réelle de la chaîne, alors que strlen() et équivalent supposent une chaîne C (terminée par un caractère nul).
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  11. #11
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Tu veux dire que ta std::string contient des données brutes, contenant potentiellement des octets nuls?
    A vrai dire, l'octet nul n'est qu'un des caractères qui puisse poser problème...

    Je pense notamment aux caractères BELL, BS, CR, CAN et tant d'autres de la table ASCII qui risquent de provoquer certains désagréments si on essaye de les utiliser dans une chaine de caractères
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  12. #12
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    À mon avis, std::string peut tout-à-fait marcher, mais il faut s'assurer que tout ce qui dépend de la longueur de la chaîne utilise std::string::length() et absolument pas strlen() ni un équivalent: length() retournera toujours la longueur réelle de la chaîne, alors que strlen() et équivalent supposent une chaîne C (terminée par un caractère nul).
    De fait, mais c'est la raison pour laquelle je préfères (mais tu as peut etre des raisons valables de me contredire sur ce point ) considérer les données récupérées comme s'il s'agissait de donner de n'importe quel type différents du caractères, et les placer, "simplement", dans un tableau "classique" plutôt que dans une classe qui "traine avec elle" la notion de chaine de caractères... affichables
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  13. #13
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    82
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 82
    Points : 25
    Points
    25
    Par défaut
    Vous venez de confirmer mes doutes, j'avais penser que cela pouvait venir du fait que ce soit des données binaires, mais en effet je n'avais pas pensé que certains octet seraient considérés comme des '\0'.
    La solution que tu propose koala01, m'était venu à l'esprit, et maintenant que vous m'avez ouvert les yeux, tu as tout as fait raison.
    Je vais implémenter tout ça, mais je vais peut-être plûtot utiliser un QByteArray, fournis par Qt.

    Et puis quel imbécile je fait, bien sûr que ça marchait mon histoire avec le fichier puisque j'écrivais dedans en mode binary...

  14. #14
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Le QByteArray de Qt est, peut être, une solution adéquate, mais...

    N'oublie pas non plus que cela introduit une dépendance envers Qt bien plus loin dans ton code "métier"...

    Tu peux, tout à fait, te baser sur le fait que même le code métier sera systématiquement utilisé avec Qt, mais, ce sera bloquant si tu souhaite être en mesure d'utiliser ton code méter avec, pourquoi pas, bibliothèque différente de Qt (WxWidget, VCL ou framework microsoft).

    N'oublie pas que toute décision à ce niveau est susceptible d'apporter autant d'avantages que d'inconvénients, et qu'il faut donc prendre la peine de faire la balance par rapport à tes objectifs
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  15. #15
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    82
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 82
    Points : 25
    Points
    25
    Par défaut
    Je suis tout à fait d'accord avec toi, c'est vrai qu'en utilisant un QByteArray, surtout dans cette partie de mon code, je restreint la compatibilité à ce framework uniquement.
    Le logiciel que je conçois est en fait un projet de fin d'étude, et je ne prévois pas d'utiliser un autre framework. Puis au pire, je vais en faire 2 versions, une avec un QByteArray et l'autre avec une solution standard, j'archiverai cette dernière, au cas où qu'un jour je puisse en avoir besoin.

    Je te remercie de tes bons conseils koala01.
    Je vais demander à mon coéquipier d'effectuer les changements en conséquence sur sa partie pour qu'elle puisse fonctionner avec la mise à jour que je viens d'effectuer dans mon code. Je mettrai en résolu à ce moment là si le problème a disparu .

  16. #16
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    La remarque avait surtout pour objectif de t'inciter à suivre le raisonnement jusqu'au bout

    Pour le reste, une fois que tu a pris les décisions qui te semblent adaptées au projet et à ses évolutions, il n'y a pas de mauvais choix
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

Discussions similaires

  1. Problème avec la methode c_str() de std::string
    Par kzwix dans le forum Langage
    Réponses: 7
    Dernier message: 08/12/2010, 12h23
  2. Problème avec la method Get
    Par Mat67 dans le forum Langage
    Réponses: 10
    Dernier message: 25/06/2007, 12h13
  3. Réponses: 3
    Dernier message: 12/04/2007, 10h47
  4. Réponses: 2
    Dernier message: 24/10/2005, 10h23
  5. [IDHTTP] Problème avec la methode post (login:pass@ww.url)
    Par Rayek dans le forum Web & réseau
    Réponses: 5
    Dernier message: 11/07/2005, 10h03

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