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

Langage Delphi Discussion :

Bug concaténation de chaines ?


Sujet :

Langage Delphi

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    116
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 116
    Points : 112
    Points
    112
    Par défaut Bug concaténation de chaines ?
    Bonjour à tous,

    voila j'ai eu un petit problème que j'ai réussi à surmonter, mais je ne comprends pas le comportement du compilateur, et je ne trouve aucune info dans la doc à ce sujet.

    Je m'explique.

    Soit dans un texte stocké dans un TMemoryStream, par ex: '###ABCD###'

    je veux récupérer le texte entre les #.
    Je lis caractère par caractère.
    Soit B, la variable Buffer qui contient chaque caractère lu dans TMemoryStream.

    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
    ...
    var
    ...
      Cache: TMemoryStream;
    ...
    begin
    ...
      while Cache.Position < Cache.Size do
      begin
        F := '';
        Cache.ReadBuffer(Pointer(B)^, 1);
        if B = '#' then
        begin
     
          while B = '#' do
          begin
            Cache.ReadBuffer(Pointer(B)^, 1);
          end;
     
          while B <> '#' do
          begin
              F := F + B
            Cache.ReadBuffer(Pointer(B)^, 1);    // <== Lorsque B recoit la nouvelle valeur, F aussi !
          end;
          ShowMessage(F);
        end;
      end;
    Le résultat serait 'BBCD' au lieu de 'ABCD'

    voila le code fonctionnant :
    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
    ...
    var
    ...
      Cache: TMemoryStream;
    ...
    begin
    ...
      while Cache.Position < Cache.Size do
      begin
        F := '';
        Cache.ReadBuffer(Pointer(B)^, 1);
        if B = '#' then
        begin
    
          while B = '#' do
          begin
            Cache.ReadBuffer(Pointer(B)^, 1);
          end;
    
          while B <> '#' do
          begin
            if F <> '' then
              F := F + B
            else
              F := Copy(B, 0, 1);    //   <== Cela résout le problème
            Cache.ReadBuffer(Pointer(B)^, 1);
          end;
          ShowMessage(F);
        end;
      end;
    Si je comprends bien, lors d'une affectation d'une string par ex:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    T := '';
    Z := 'B':
     
    T := T + Z;
    Z := 'J';  //  <=  Lorsque Z reçoit 'J', T aussi !?
    j'ai l'impression que comme T est "vide" lors de l'affectation, le compilateur ne copie pas le contenu mais stocke juste l'adresse du string copié, mais lors de la 2ème itération, T n'étant plus vide, cette fois-ci le contenu est bel et bien copié.
    Le fait d'utiliser la fonction Copy résout le problème.

    Quelqu'un pourrait m'apporter des précisions svp ?


    Merci à vous,

    Fred

  2. #2
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 448
    Points
    28 448
    Par défaut
    arf !

    utilise ceci et ça ira bcp mieux !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
     Cache.ReadBuffer(B, 1);
    c'est juste la variable B (qui je suppose est un char) que tu veux remplir, le transtypage en pointer est des plus douteux
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    116
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 116
    Points : 112
    Points
    112
    Par défaut
    Merci Paul,

    non cela ne marche pas avec les TMemoryStream, obligé de transtyper en pointeur.

    La solution je l'ai, c'est l'explication que je n'ai pas !!

    apparement oui c'est le transtypage en pointeur qui fait que cela se comporte de la sorte, je trouve juste bizarre que cela ne soit pas "clair'

  4. #4
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 448
    Points
    28 448
    Par défaut
    ah non !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    procedure TStream.ReadBuffer(var Buffer; Count: Longint);
    Buffer est non typé, tu peux passer ce que tu veux...au pire, pour détyper B, tu pourrais écrire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
     Stream.ReadBuffer(pointer(@B)^,1)
    mais c'est inutile.
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  5. #5
    Expert éminent Avatar de Graffito
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    5 993
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 993
    Points : 7 903
    Points
    7 903
    Par défaut
    Bonjour,

    Hormis le cast (plutôt mettre qq chose du genre Pointer(@B)^ ) et en supposant que B est un Char et F une String, le code initial m'a l'air OK .
    1) tester en supprimant l'optimisation dans les options du projet,
    2) tester en pas à pas pour voir la valeur de B après chaque read et avant de concaténer à F.
    " Le croquemitaine ! Aaaaaah ! Où ça ? " ©Homer Simpson

  6. #6
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 448
    Points
    28 448
    Par défaut
    AAHHHHHH ! mais n'aurais tu pas déclaré B comme étant un STRING ?!

    ce qui serait d'une part très bête, mais qui d'autre part expliquerait que ça fonctionne malgré tout.

    mais dans ce cas

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    // allouer de l'espace pour 1 caractère
     SetLength(B,1);
    // ensuite remplacement de ce caractère
     Stream.ReadBuffer(s[1],1);
    // ou encore, mais plus casse gueule
     Stream.ReadBuffer(pointer(s)^,1);
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    116
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 116
    Points : 112
    Points
    112
    Par défaut
    Citation Envoyé par Paul TOTH Voir le message
    AAHHHHHH ! mais n'aurais tu pas déclaré B comme étant un STRING ?!
    Hormis les détails techniques, je bute sur votre phrase. Pourquoi très bête ? (Effectivement B est un string)

    Ne connaissant rien aux streams, j'ai cherché des tutoriaux dont je me suis inspiré.

    Dont :
    http://dn.codegear.com/article/26416

    je pensais que l'on était pas obligé de spécifier le type le plus approprié et que le compilateur se débrouillait tout seul pour les affectations mémoires...

    Je maintiens que votre solution ne fonctionne pas

    Ex:
    http://mc-computing.com/Languages/Delphi/Streams.html

  8. #8
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 448
    Points
    28 448
    Par défaut
    Citation Envoyé par fred64 Voir le message
    Hormis les détails techniques, je bute sur votre phrase. Pourquoi très bête ? (Effectivement B est un string)
    ben parce que tu veux lire un char et pas un string, et que les string c'est intéressant mais ça cache l'essentiel

    Citation Envoyé par fred64 Voir le message
    Ne connaissant rien aux streams, j'ai cherché des tutoriaux dont je me suis inspiré.

    Dont :
    http://dn.codegear.com/article/26416

    je pensais que l'on était pas obligé de spécifier le type le plus approprié et que le compilateur se débrouillait tout seul pour les affectations mémoires...
    ben, non d'ailleurs c'est écrit en toutes lettres :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
     // Set the length, so we have space to read into
      SetLength(SourceString, MemoryStream.Size);
    Citation Envoyé par fred64 Voir le message
    Je maintiens que votre solution ne fonctionne pas
    et bien change de soutien
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    116
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 116
    Points : 112
    Points
    112
    Par défaut
    Vous me faites bien rire Paul....

    Evidemment que dans mon code d'origine, le setlength à 1 était fait sur le string.
    (Bien que cela n'était pas dans le 1er bout de code montré, j'en conviens)

    Mais a ma question du pourquoi vous n'avez pas été capable de répondre directement, cela est la preuve que vous non plus n'avez pas compris tout au problème.

    Maintenant, pour vous paraphraser, c'est également "très bête" d'écrire un livre sur Delphi et de découvrir la directive implements des années après...

    Cela ne m'a pas choqué sauf depuis que vous utilisez votre ton narquois et péremptoire.

    Je m'interesse plus au pourquoi cela ne marchait pas (alors que j'avais la solution, trouvée par moi même) plutot que de recopier bêtement des bouts de code.

    Ce genre de réponse :
    ben parce que tu veux lire un char et pas un string, et que les string c'est intéressant mais ça cache l'essentiel
    prouve bien que, bien que ne maitrisant pas tout l'aspect du problème en question vous vous permettez de donner des réponses vagues et évasives pour cacher le fait que vous non plus vous ne savez pas le "pourquoi".

    Maintenant, je n'ai pas de doute sur le fait que mon message sera certainement censuré ou descendu en flamme...


    Fred

  10. #10
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 448
    Points
    28 448
    Par défaut
    Citation Envoyé par fred64 Voir le message
    Vous me faites bien rire Paul....
    c'est déjà ça !
    Citation Envoyé par fred64 Voir le message
    Evidemment que dans mon code d'origine, le setlength à 1 était fait sur le string.
    (Bien que cela n'était pas dans le 1er bout de code montré, j'en conviens)

    Mais a ma question du pourquoi vous n'avez pas été capable de répondre directement, cela est la preuve que vous non plus n'avez pas compris tout au problème.

    Maintenant, pour vous paraphraser, c'est également "très bête" d'écrire un livre sur Delphi et de découvrir la directive implements des années après...
    ben je connais pas tout et je l'affirme haut et fort contrairement à d'autres qui en connaissant un peu prétendent tout savoir !

    Citation Envoyé par fred64 Voir le message

    Cela ne m'a pas choqué sauf depuis que vous utilisez votre ton narquois et péremptoire.

    Je m'interesse plus au pourquoi cela ne marchait pas (alors que j'avais la solution, trouvée par moi même) plutot que de recopier bêtement des bouts de code.

    Ce genre de réponse :
    prouve bien que, bien que ne maitrisant pas tout l'aspect du problème en question vous vous permettez de donner des réponses vagues et évasives pour cacher le fait que vous non plus vous ne savez pas le "pourquoi".
    ah ? elle est où l'explication de ce phénomène étrange et pénétrant ?

    Citation Envoyé par fred64 Voir le message

    Maintenant, je n'ai pas de doute sur le fait que mon message sera certainement censuré ou descendu en flamme...

    Fred
    ouais ! on a bientôt atteins le point GodWin !!!
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  11. #11
    Expert éminent Avatar de Graffito
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    5 993
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 993
    Points : 7 903
    Points
    7 903
    Par défaut
    Tu verra mieux ce qui s'est passé en insérant après F:=F+B l'instruction:
    ShowMessage('F='+F+inttostr(length(F)+' / B='+B+inttostr(length(B)) ;
    " Le croquemitaine ! Aaaaaah ! Où ça ? " ©Homer Simpson

  12. #12
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    116
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 116
    Points : 112
    Points
    112
    Par défaut
    Merci Graffito pour ton aide.

    J'ai fais sortir les infos comme tu me l'as conseillé et je vois bien qu'a la premiere itération tout se passe comme si F etait un pointeur sur B, à la seconde itération, F n'étant plus vide, la concaténation se fait bien..

    J'avais trouvé la solution mais j'essayais de comprendre le dysfonctionnement...

    je vais arreter de me poser trop de question et je vais publier des livres

    Merci,


    Fred

  13. #13
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    116
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 116
    Points : 112
    Points
    112
    Par défaut
    Citation Envoyé par Paul TOTH Voir le message
    ouais ! on a bientôt atteins le point GodWin !!!
    Dixit Wikipedia :

    certains considèrent que le fait de clore un débat en invoquant cette loi n'est qu'une façon de fuir la discussion avec ceux qui n'ont pas utilisé ce genre de comparaisons (ie: comparaison avec les nazis)

  14. #14
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 448
    Points
    28 448
    Par défaut
    Citation Envoyé par fred64 Voir le message
    Merci Graffito pour ton aide.

    J'ai fais sortir les infos comme tu me l'as conseillé et je vois bien qu'a la premiere itération tout se passe comme si F etait un pointeur sur B, à la seconde itération, F n'étant plus vide, la concaténation se fait bien..
    puisque tu aimes les citations :

    Citation Envoyé par Borland Delphi
    Comme les variables chaîne longue sont des pointeurs, plusieurs peuvent pointer sur la même valeur sans utiliser de mémoire supplémentaire. Le compilateur utilise ceci pour économiser les ressources et exécuter les affectations plus rapidement.
    or toi tu manipules des pointeurs...cherchez l'erreur !

    Citation Envoyé par fred64 Voir le message
    J'avais trouvé la solution mais j'essayais de comprendre le dysfonctionnement...
    le dysfonctionnement est dans ta façon d'utiliser ReadBuffer

    Citation Envoyé par fred64 Voir le message

    je vais arreter de me poser trop de question et je vais publier des livres
    bonne idée !
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

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

Discussions similaires

  1. Comment concaténer une chaine de caractères avec un espace ?
    Par blanchonvincent dans le forum MATLAB
    Réponses: 6
    Dernier message: 07/04/2007, 21h53
  2. Réponses: 2
    Dernier message: 02/04/2007, 11h07
  3. Réponses: 1
    Dernier message: 25/04/2006, 16h06
  4. Concaténéation de chaine dans un group by
    Par Delphi-ne dans le forum Requêtes
    Réponses: 4
    Dernier message: 28/01/2006, 00h11
  5. Bug strtok sur chaine de type x;y;;z
    Par CanardJM dans le forum C
    Réponses: 15
    Dernier message: 05/01/2006, 10h16

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