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++Builder Discussion :

Le sprintf de AnsiString, bug ou pas?


Sujet :

C++Builder

Vue hybride

Message pr�c�dent Message pr�c�dent   Message suivant Message suivant
  1. #1
    Membre exp�riment�
    Homme Profil pro
    Enseignant
    Inscrit en
    Mars 2012
    Messages
    164
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activit� : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2012
    Messages : 164
    Par d�faut Le sprintf de AnsiString, bug ou pas?
    en tentant de r�pondre au probl�me de commande SQL de faniette, je me souvenu d'un "bug" que j'avais cherch� longtemps, soit un "(null)" qui s'ins�rait dans un champ de table de donn�es.

    J'ai fini par le trouver, me suis demand� s'il y avait un bug dans la m�thode de "sprintf" de AnsiString ou si c'�tait une subtilit� qui m'�chappait.

    Voil� le bug(?)
    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
     
    {
      AnsiString dest,buf ;
     
      buf = "allo" ;
      dest.sprintf("1- une string: [%s]",buf) ;
      ShowMessage(dest) ;
     
      buf = "" ;
      dest.sprintf("2- une string: [%s]",buf) ;
      ShowMessage(dest) ;
     
      dest.sprintf("3- une string: [%s]",buf.c_str()) ;
      ShowMessage(dest) ;
    }
    Voici ce qui sera affich�:
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
     
    1- une string: [allo]
    2- une string: [(null)]
    3- une string: []
    La version #2, vous trouvez �a normal ou pas?

    Et vous trouvez normal, vous voulez m'expliquer pourquoi?

  2. #2
    Membre Expert
    Avatar de DjmSoftware
    Homme Profil pro
    Responsable de compte
    Inscrit en
    Mars 2002
    Messages
    1 044
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activit� : Responsable de compte
    Secteur : High Tech - Op�rateur de t�l�communications

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 044
    Billets dans le blog
    1
    Par d�faut
    Salut Guyt
    dans le cas 2 tu copie un objet d'on tu ignore le contenu puis qu'il n'a pas �t� initialis�.

    dans le cas 3 c'est bien une cha�ne de caract�re qui est copi�e dans ton buffer
    la m�thode .c_str() te retourne le contenu de ton buffer.

    cdlt
    vous trouverez mes tutoriels � l'adresse suivante: http://djmsoftware.developpez.com/
    je vous en souhaite une excellente lecture ...

    A lire : Les r�gles du forum

  3. #3
    Membre exp�riment�
    Homme Profil pro
    Enseignant
    Inscrit en
    Mars 2012
    Messages
    164
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activit� : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2012
    Messages : 164
    Par d�faut
    Citation Envoy� par DjmSoftware Voir le message
    Salut Guyt
    dans le cas 2 tu copie un objet d'on tu ignore le contenu puis qu'il n'a pas �t� initialis�.
    cdlt
    Na, je comprends toujours pas, y a une subtilit� qui m'�chappe.

    Juste avant le cas 2, je fais:
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
     
    buf= "" ;  // ce qui serait équivalent à buf = AnsiString("") ;
    dest.sprintf("2- une string: [%s]",buf) ;
    J�initialise bien la chaine avec une chaine vide, le contenu je le connais, c'est une string de longueur z�ro!

    Tiens, je te balance une autre curiosit�:

    Un bouton, une TEdit avec "Edit1" dans sa propri�t� Text.

    Le code:
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
     
    void __fastcall TForm3::Button1Click(TObject *Sender)
    {
      AnsiString stg ;
     
      stg.sprintf("%s",Edit1->Text) ;
      ShowMessage(stg) ;
      stg.sprintf("%s",AnsiString(Edit1->Text)) ;
      ShowMessage(stg) ;
    }
    ce qui sera affich�:
    Ouate de phoque???

  4. #4
    Membre Expert
    Avatar de DjmSoftware
    Homme Profil pro
    Responsable de compte
    Inscrit en
    Mars 2002
    Messages
    1 044
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activit� : Responsable de compte
    Secteur : High Tech - Op�rateur de t�l�communications

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 044
    Billets dans le blog
    1
    Par d�faut
    Salut
    Ne confond pas un string qui correspond � un tableau de caract�re avec un Ansistring qui lui est un object
    %s correspond � une cha�ne de caract�re
    Dans ton premier exemple tu ressort le premier caract�re normal en Unicode le caract�re suivant est un 0
    Dans ton second exemple tu construit un object de type Ansistring � partir d'un object unicode
    La syntaxe correcte est de suffixer avec un c_str ou. T_str
    Cdlt
    vous trouverez mes tutoriels � l'adresse suivante: http://djmsoftware.developpez.com/
    je vous en souhaite une excellente lecture ...

    A lire : Les r�gles du forum

  5. #5
    Membre exp�riment�
    Homme Profil pro
    Enseignant
    Inscrit en
    Mars 2012
    Messages
    164
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activit� : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2012
    Messages : 164
    Par d�faut
    Citation Envoy� par DjmSoftware Voir le message
    Salut
    La syntaxe correcte est de suffixer avec un c_str ou. T_str
    Cdlt
    C'est ce que je faisais depuis un bon bout de temps, sans savoir exactement pourquoi.

    Maintenant je le sais, un gros merci!

  6. #6
    Expert �minent
    Avatar de ShaiLeTroll
    Homme Profil pro
    D�veloppeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 089
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 44
    Localisation : France, Seine Saint Denis (�le de France)

    Informations professionnelles :
    Activit� : D�veloppeur C++\Delphi
    Secteur : High Tech - �diteur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 089
    Par d�faut
    J'avais m�me d�pos� une demande sur Quality Central pour que le sprintf (plus �l�gant et performant que le Format ARRAYOFCONST) �mettent un Warning lors de l'utilisation d'un String comme param�tre !

    Je suis d'accord avec Guyt54, la documentation de UnicodeString.sprintf ou AnsiString.sprintf ne fournis aucun avertissement, c'est bien dommage, de plus le lien vers Format renforce la confusion car cette fonction supporte les objets comme param�tre (puisque c'est du code Delphi)

    Venant du Delphi et ayant l'habitude du Format, je pensais utilise ce dernier mais la template ARRAYOFCONST m'a d�courag� vu le code que cela g�n�re assez inf�me du coup, je suis pass� au sprintf !
    J'ai b�tement �crit ceci

    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
    {
      UnicodeString S1 = "Chaine S1";
      UnicodeString S2 = "Chaine S2";
      UnicodeString S3 = "Chaine S3";
      UnicodeString S4 = "Chaine S4";
      UnicodeString S5 = "Chaine S5";
      UnicodeString S6 = "Chaine S6";
      UnicodeString LocalStr = "";
     
      for (int i = 0; i < 10; i++)
      {
        S1 += UnicodeString().sprintf(L"%s %d", EmptyStr, i);
        S2 += UnicodeString().sprintf(L"%s %d", "", i);
        S3 += UnicodeString().sprintf(L"%s %d", LocalStr, i);
     
        S4 += Format(L"%s %d", ARRAYOFCONST((EmptyStr, i)));
        S5 += Format(L"%s %d", ARRAYOFCONST(("", i)));
        S6 += Format(L"%s %d", ARRAYOFCONST((LocalStr, i)));
      }
      MemoTrace->Lines->Add("sprintf");
      MemoTrace->Lines->Add(S1);
      MemoTrace->Lines->Add(S2);
      MemoTrace->Lines->Add(S3);
      MemoTrace->Lines->Add("Format");
      MemoTrace->Lines->Add(S4);
      MemoTrace->Lines->Add(S5);
      MemoTrace->Lines->Add(S6);
    }
    Avec ce beau r�sultat :

    Result actually

    sprintf
    Chaine S1(null) 0(null) 1(null) 2(null) 3(null) 4(null) 5(null) 6(null) 7(null) 8(null) 9
    Chaine S2 0 1 2 3 4 5 6 7 8 9
    Chaine S3(null) 0(null) 1(null) 2(null) 3(null) 4(null) 5(null) 6(null) 7(null) 8(null) 9
    Format
    Chaine S4 0 1 2 3 4 5 6 7 8 9
    Chaine S5 0 1 2 3 4 5 6 7 8 9
    Chaine S6 0 1 2 3 4 5 6 7 8 9

    Result expected

    sprintf
    Chaine S1 0 1 2 3 4 5 6 7 8 9
    Chaine S2 0 1 2 3 4 5 6 7 8 9
    Chaine S3 0 1 2 3 4 5 6 7 8 9
    Format
    Chaine S4 0 1 2 3 4 5 6 7 8 9
    Chaine S5 0 1 2 3 4 5 6 7 8 9
    Chaine S6 0 1 2 3 4 5 6 7 8 9

    Leur r�ponse sur QC fut : "Please try to add .c_str() as below, because EmptyStr and LocalStr are instances of UnicodeString class."
    Belle Astuce, j'aurais bien aim� qu'elle soit dans la Documentation, j'aurais �vit� une perte de temps !
    D'ailleurs, c'�tait aussi pour g�n�rer du SQL � la vol�e via ma couche d'objet persistant tout en utilisant les Parameters pour simplifier le typage des champs\propri�t�s

    les AnsiString sont des objets en allocation statique, le constructeur d�fini la cha�ne sur un pointeur NULL qui est g�r� par le C++ tout comme en Delphi, il y avait m�me une constante pr�vue � cet effet (avant on ne pouvait pas d�finir '' ou "" directement, il fallait utiliser la constante EmptyStr

    Et le (null) est tout simplement la valeur du membre priv� Data dans la AnsiString !
    Tout en rappelant que Data[-12] pointe sur StrRec et que le code d'allocation des chaines est �crit en Delphi !


    J'ai conserv� un petit code (j'ai aussi une version UnicodeString) pour me rappeler de cette surprise !

    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
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    //---------------------------------------------------------------------------
    void __fastcall TLanguageBasicsForm::BtnReveiverAndParametersprintfClick(TObject *Sender)
    {
      MemoTrace->Lines->Add("S.sprintf(\"%s %d\", S, i++);");
      AnsiString SP1 = "Chaine SP1";
      AnsiString SP2 = "Chaine SP2";
      AnsiString SP3 = "Chaine SP3";
      AnsiString SP4 = "Chaine SP4";
      AnsiString SP4c = "Chaine SP4c";
      AnsiString SP5 = "Chaine SP5";
      AnsiString SP6 = "Chaine SP6";
      AnsiString SP6c = "Chaine SP6c";
      AnsiString SP7 = "Chaine SP7";
      AnsiString SF1 = "Chaine SF1";
      AnsiString SF2 = "Chaine SF2";
      AnsiString SF3 = "Chaine SF3";
     
      for (int i = 0; i < 10; i++)
      {
        SP1.sprintf("%s %d", SP1, i);
        SP2 = AnsiString().sprintf("%s %d", SP2, i);
        SP3 += ", ";
        SP3 += AnsiString().sprintf("%d", i);
        SP4 += AnsiString().sprintf("%s %d", EmptyStr, i);
        SP4c += AnsiString().sprintf("%s %d", EmptyStr.c_str(), i);
        SP5 += AnsiString().sprintf("%s %d", "", i);
        AnsiString LocalStr = "";
        SP6 += AnsiString().sprintf("%s %d", LocalStr, i);
        SP6c += AnsiString().sprintf("%s %d", LocalStr.c_str(), i);
        SP7 += AnsiString().sprintf("%s %d", AnsiString(this->ClassName()).c_str(), i);
     
        SF1.Format("%s %d", ARRAYOFCONST((SF1, i)));
        SF2 += AnsiString().Format("%s %d", ARRAYOFCONST((EmptyStr, i)));
        SF3 += AnsiString().Format("%s %d", ARRAYOFCONST((LocalStr, i)));
      }
      MemoTrace->Lines->Add("sprintf");
      MemoTrace->Lines->Add(SP1);
      MemoTrace->Lines->Add(SP2);
      MemoTrace->Lines->Add(SP3);
      MemoTrace->Lines->Add(SP4);
      MemoTrace->Lines->Add(SP4c);
      MemoTrace->Lines->Add(SP5);
      MemoTrace->Lines->Add(SP6);
      MemoTrace->Lines->Add(SP6c);
      MemoTrace->Lines->Add(SP7);
      MemoTrace->Lines->Add("Format");
      MemoTrace->Lines->Add(SF1);
      MemoTrace->Lines->Add(SF2);
      MemoTrace->Lines->Add(SF3);
     
      MemoTrace->Lines->Add("sprintf too params : " + AnsiString().sprintf("a %d b %d c %d", 1, 2, 3, 4, 5, 6));
      MemoTrace->Lines->Add("sprintf missing params : " + AnsiString().sprintf("a %d b %d c %d", 1, 2));
     
      MemoTrace->Lines->Add("sprintf %8x et %08x");
      int i = 123;
      MemoTrace->Lines->Add(AnsiString().sprintf("%8x", i));
      MemoTrace->Lines->Add(AnsiString().sprintf("%08x", i));
      MemoTrace->Lines->Add(AnsiString().sprintf("%01x", i));
      MemoTrace->Lines->Add(AnsiString().sprintf("%d", i));
      MemoTrace->Lines->Add(AnsiString().sprintf("%06d", i));
      MemoTrace->Lines->Add(AnsiString().sprintf("%02d", i));
      bool flag = true;
      MemoTrace->Lines->Add(AnsiString().sprintf("Boolean true = %d", flag));
      flag = false;
      MemoTrace->Lines->Add(AnsiString().sprintf("Boolean false = %d", flag));
    }
    Aide via F1 - FAQ - Guide du d�veloppeur Delphi devant un probl�me - Pensez-y !
    Attention Troll M�chant !
    "Quand un homme a faim, mieux vaut lui apprendre � p�cher que de lui donner un poisson" Confucius
    Mieux vaut se taire et para�tre idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la m�diocrit� !

    L'exp�rience, c'est le nom que chacun donne � ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

+ R�pondre � la discussion
Cette discussion est r�solue.

Discussions similaires

  1. bug excel pas ordinaire calendrier fantôme
    Par alsimbad dans le forum Macros et VBA Excel
    R�ponses: 7
    Dernier message: 03/12/2006, 18h59
  2. FB: DB vide, impossible de connecter : Bug ou Pas Bug ?
    Par Rica dans le forum Connexion aux bases de donn�es
    R�ponses: 1
    Dernier message: 14/05/2005, 11h15

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