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 :

Compter le nombre d'espaces en début de chaîne


Sujet :

Langage Delphi

  1. #1
    Membre émérite

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 388
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 388
    Points : 2 999
    Points
    2 999
    Par défaut Compter le nombre d'espaces en début de chaîne
    Bonjour

    Bien sûr, je sais faire. Mais très basiquement, j'ai fais ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
      function NombreEspacesDebut(Chaine: string): Integer;
      var
        I: Integer;
      begin
        Result := 0;
        for I := 1 to Length(Chaine) do
          if Chaine[I] = ' ' then
            Inc(Result)
          else
            Break;
      end;
    Mais est-ce vraiment optimisé ?

  2. #2
    Membre expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    661
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Deux Sèvres (Poitou Charente)

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

    Informations forums :
    Inscription : Novembre 2006
    Messages : 661
    Points : 3 630
    Points
    3 630
    Billets dans le blog
    2
    Par défaut
    Bonjour,

    Plusieurs solutions sont évidemment possibles. Voici la code de la fonction NombreEspacesDebut modifiée avec 3 solutions différentes (que j'ai commenté/décommenté en fonction des tests).

    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
    function NombreEspacesDebut(Chaine: string): Integer;
    var
        I: Integer;
    begin
    // Solution 1 : via regexp
      result := TRegEx.Create('^\s*').Match(chaine).length;
     
    // Solution 2 : via trimleft
    //  result := length(chaine) - trimleft(chaine).Length;
     
    // Solution 3 : la boucle
    //    Result := 0;
    //    for I := 1 to Length(Chaine) do
    //      if Chaine[I] = ' ' then
    //        Inc(Result)
    //      else
    //        Break;
    end;
    Je n'ai pas fait de tests de performance très poussés (appel 1000 fois à la fonction NombreEspacesDebut avec une chaîne de caractères à laquelle j'ajoute un espace au début à chaque itération de la boucle et affichage des résultats (chaine + le résultat de la fonction dans un TMemo).

    La solution la plus rapide semble être celle avec les expressions régulières mais c'est vraiment très proche des solutions avec trimleft. La boucle proposée par papy214 est la plus lente (je ne l'aurai pas cru) : elle prend 120 ms de plus que la solution par regexp.

    Ensuite d'un point de vue lisibilité du code, les solutions via regexp et trimleft tiennent sur une ligne
    Mon site - Mes tutoriels - GitHub - N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  3. #3
    Membre émérite

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 388
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 388
    Points : 2 999
    Points
    2 999
    Par défaut
    C'est vrai que le TrimLeft éviterait même la fonction puisque ça tient sur une ligne.
    Pour la boucle, je me doutais que ce n'est pas le top.
    Par contre, que TRegex soit aussi performant, je ne l'aurais pas cru.

  4. #4
    Membre éprouvé
    Avatar de Cirec
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    467
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 467
    Points : 1 072
    Points
    1 072
    Par défaut
    Bonjour,

    le code que je vous propose est plus rapide que la RegEx.
    Selon mes testes, très simplistes, pour 10000 itérations le code ci-dessous est 1 seconde plus rapide que l'expression régulière.
    Et tout comme gbegreg à chaque boucle j'ajoute un espace.
    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
    implementation
     
    {$R *.dfm}
    uses System.RegularExpressions, System.Diagnostics;
     
    function CountLSpace(const aStr: string): Integer;
    var I, L: Cardinal;
      PB: PByte;
    begin
      PB := @aStr[1];
      L := SizeOf(Char);
      Result := 0;
      while (Pb^ <> $0) and (Pb^ = $20) do begin
        Inc(Result);
        Inc(Pb, L);
      end;
    end;
     
    procedure TForm2.Button1Click(Sender: TObject);
    var aStr: string;
      St: TStopwatch;
      I: Integer;
    begin
      aStr := 'Test';
      Memo1.Lines.BeginUpdate;
      try
        st := TStopwatch.Create;
        St.Start;
        for I:= 0 to 10000 do begin
          Memo1.Lines.Add(CountLSpace(aStr).ToString);
          aStr := ' ' + aStr;
        end;
      finally
        Memo1.Lines.EndUpdate;
      end;
      St.Stop;
      Memo1.Lines.Add(St.Elapsed.ToString);
    end;
     
    procedure TForm2.Button2Click(Sender: TObject);
    var aStr: string;
      St: TStopwatch;
      I: Integer;
    begin
      aStr := 'Test';
      Memo1.Lines.BeginUpdate;
      try
        st := TStopwatch.Create;
        St.Start;
        for I:= 0 to 10000 do begin
          Memo1.Lines.Add(TRegEx.Create('^\s*').Match(aStr).length.ToString);
          aStr := ' ' + aStr;
        end;
      finally
        Memo1.Lines.EndUpdate;
      end;
      St.Stop;
      Memo1.Lines.Add(St.Elapsed.ToString);
    end;
     
    end.
    Cordialement,
    @+

  5. #5
    Membre émérite

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 388
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 388
    Points : 2 999
    Points
    2 999
    Par défaut
    uniquement en déplaçant le pointeur, joli.
    Je suis toujours étonné que plus de code puisse être plus rapide mais apparemment ça arrive .

  6. #6
    Membre expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    661
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Deux Sèvres (Poitou Charente)

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

    Informations forums :
    Inscription : Novembre 2006
    Messages : 661
    Points : 3 630
    Points
    3 630
    Billets dans le blog
    2
    Par défaut
    Merci Cirec : je ne connaissais pas l'unité System.Diagnostics. Je jouais avec des variables TDateTime pour déterminer le délai écoulé mais maintenant j'utiliserai ces fonctionnalités.

    PS : à noter que l'expression régulière "^\s*" ne teste pas uniquement les espaces mais également les tabulations, retours chariots, retours à la ligne... (tous les caractères "blancs").
    Mon site - Mes tutoriels - GitHub - N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  7. #7
    Membre expérimenté Avatar de guillemouze
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    876
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Novembre 2004
    Messages : 876
    Points : 1 448
    Points
    1 448
    Par défaut
    Plusieurs remarques concernant ta réponse Cirec :
    • tu regarde la taille d'un char, mais tu ne compare que le premier octet, donc ne fonctionne pas avec une chaine utf16 (dans l'absolu, mais en pratique tu as peu de chances de tomber sur un des 255 caractères qui posent problème)
    • (Pb^ <> $0) and (Pb^ = $20) = Pb^ = $20


    voici ton code, un peu amélioré :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    function CountLSpace(const s: string): Cardinal;
    var
      pc: pchar;
    begin
      Result := 0;
      if Length(s) = 0 then Exit;
      pc := @s[1];
      while pc^ = ' ' do
      begin
        inc(Result);
        inc(pc);
      end;
    end;

  8. #8
    Membre éprouvé
    Avatar de Cirec
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    467
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 467
    Points : 1 072
    Points
    1 072
    Par défaut
    re,
    Citation Envoyé par Papy214 Voir le message
    uniquement en déplaçant le pointeur, joli.
    Je suis toujours étonné que plus de code puisse être plus rapide mais apparemment ça arrive .
    ce n'est pas le nombre de lignes qui impacte sur la rapidité du code mais comment Delphi le converti en code machine
    souvent un code développé fonctionnera plus vite qu'un code plus compacte
    Exemple ci-dessous la première version met entre 5 et 6 secondes alors que le deuxième met 0.5 seconde
    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
    const
      nBoucle: Integer = 100000000;
    var
      IntTab: array[1..10] of Integer;
     
    procedure TForm2.Button3Click(Sender: TObject);
    var
      St: TStopwatch;
      I, J: Integer;
    begin
        st := TStopwatch.Create;
        St.Start;
        for I:= 0 to nBoucle do begin
           for J:= 1 to 10 do IntTab[J] := 0;
        end;
      St.Stop;
      Memo1.Lines.Add(St.Elapsed.ToString);
    end;
     
     
    procedure TForm2.Button4Click(Sender: TObject);
    var
      St: TStopwatch;
      I, J: Integer;
    begin
        st := TStopwatch.Create;
        St.Start;
        for I:= 0 to nBoucle do begin
           IntTab[1] := 0;
           IntTab[2] := 0;
           IntTab[3] := 0;
           IntTab[4] := 0;
           IntTab[5] := 0;
           IntTab[6] := 0;
           IntTab[7] := 0;
           IntTab[8] := 0;
           IntTab[9] := 0;
           IntTab[10] := 0;
        end;
      St.Stop;
      Memo1.Lines.Add(St.Elapsed.ToString);
    end;
    Citation Envoyé par gbegreg Voir le message
    ...
    PS : à noter que l'expression régulière "^\s*" ne teste pas uniquement les espaces mais également les tabulations, retours chariots, retours à la ligne... (tous les caractères "blancs").
    pour cela il suffit de changer
    while (Pb^ <> $0) and (Pb^ = $20) do begin en while (Pb^ <> $0) and (Pb^ <= $20) do begin et
    le code est conforme à la RegEx.

    Citation Envoyé par guillemouze Voir le message
    • tu regarde la taille d'un char, mais tu ne compare que le premier octet, donc ne fonctionne pas avec une chaine utf16 (dans l'absolu, mais en pratique tu as peu de chances de tomber sur un des 255 caractères qui posent problème)
    • (Pb^ <> $0) and (Pb^ = $20) = Pb^ = $20
    ça fait plaisir d'échanger à nouveau avec toi
    Alors oui je regarde la taille d'un Char qui vaut 1 en Ainsi et 2 en Unicode
    et je compare le deuxième octet si Unicode.
    mais je ne vois pas quel caractère pourrait poser problème dans un Alphabet Latin ?
    peux-tu nous en dire plus ?

    quand au (Pb^ <> $0) il n'est pas si inutile que ça il teste la fin de la chaine
    d'ailleurs si on adapte le code pour qu'il soit équivalent à la RegEx il devient indispensable de tester la fin de la chaine
    sinon les valeurs de retour sont toutes fausses !!!
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    function CountLSpace(const s: string): Cardinal;
    var
      pc: pchar;
    begin
      Result := 0;
    //  if Length(s) = 0 then Exit; // Devient inutile
      pc := @s[1];
      while (Ord(pc^) <> $0) and (Ord(pc^) <= $20) do
      begin
        inc(Result);
        inc(pc);
      end;
    end;
    Cordialement,
    @+

  9. #9
    Membre expérimenté Avatar de guillemouze
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    876
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Novembre 2004
    Messages : 876
    Points : 1 448
    Points
    1 448
    Par défaut
    Citation Envoyé par Cirec Voir le message

    pour cela il suffit de changer
    while (Pb^ <> $0) and (Pb^ = $20) do begin en while (Pb^ <> $0) and (Pb^ <= $20) do begin et
    le code est conforme à la RegEx.
    Attention, dans [$1..$20], il y a d'autres caractères spéciaux. Dans ce cas, il vaudrait mieux gérer l'ensemble de caractères à gérer : not (Pb^ in [' ', #9{tab}, #160{espace insécable}])
    Citation Envoyé par Cirec Voir le message
    mais je ne vois pas quel caractère pourrait poser problème dans un Alphabet Latin ?
    peux-tu nous en dire plus ?
    Moi non plus, c'est d'ailleurs pour ca que je précise
    dans l'absolu, mais en pratique tu as peu de chances de tomber sur un des 255 caractères qui posent problème
    mais tous les caracteres qui on $20 en premier octet sont concernés, en voici la liste :
    ĠȠ̠РԠؠܠࠠठਠଠఠഠภ༠ဠᄠሠጠᐠᔠᘠᜠᠠᤠᨠᬠᰠᴠḠἠ†℠∠⌠␠┠☠✠⠠⤠⨠⬠Ⱐⴠ⸠⼠〠ㄠ㈠㌠㐠㔠㘠㜠㠠㤠㨠㬠㰠㴠㸠㼠䀠䄠䈠䌠䐠䔠䘠䜠䠠䤠䨠䬠䰠䴠丠传倠儠删匠吠唠嘠圠堠夠娠嬠尠崠帠张怠愠戠挠搠攠映朠栠椠樠欠氠洠渠漠瀠焠爠猠琠甠瘠眠砠礠稠笠簠素縠缠耠脠舠茠萠蔠蘠蜠蠠褠訠謠谠贠踠輠造鄠鈠錠鐠锠阠霠頠餠騠鬠鰠鴠鸠鼠ꀠꄠꈠꌠꐠꔠ꘠꜠ꠠꤠꨠꬠ갠괠긠꼠뀠넠눠댠될딠똠뜠렠뤠먠묠밠봠븠뼠쀠선술쌠쐠씠옠유젠줠쨠쬠찠촠츠켠퀠턠툠팠퐠픠혠휠���󘀠���鸞蘒ﬠﰠﴠ︠@
    et le code qui les génère si ca t'interesse :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    procedure TForm1.Button1Click(Sender: TObject);
    var
      c: char;
      pb: Pansichar;
      i: Integer;
    begin
      c := ' ';
      pb := @c;
      for i := 1 to 255 do // 0 etant l'espace
      begin
        pb[1] := AnsiChar(i); // remplacement du 2eme octet, le 1er reste $20
        edit1.text := edit1.text + c;
      end;
    end;
    Citation Envoyé par Cirec Voir le message
    quand au (Pb^ <> $0) il n'est pas si inutile que ça il teste la fin de la chaine
    d'ailleurs si on adapte le code pour qu'il soit équivalent à la RegEx il devient indispensable de tester la fin de la chaine
    sisi, (x <> 0) and (x = $20) si c'est $20, c'est forcément pas 0 !
    si on atteint la fin de la chaine, on tombe sur un $0, qui est forcement pas $20 donc on s'arrete. Et comme le montre le dernier article de Paul Toth, delphi ajoute automatiquement un 0 à la fin de la chaine pour pouvoir l'utiliser comme un PChar directement.
    Citation Envoyé par Cirec Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    //  if Length(s) = 0 then Exit; // Devient inutile
      pc := @s[1];
    Non pas inutile, si la longueur de s est 0, alors s = nil, donc s[1] va lire dans un endroit de ta mémoire qui ne t'appartient pas et qui contiendra une valeur aléatoire.

  10. #10
    Membre éprouvé
    Avatar de Cirec
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    467
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 467
    Points : 1 072
    Points
    1 072
    Par défaut
    Citation Envoyé par guillemouze Voir le message
    (x <> 0) and (x = $20) si c'est $20, c'est forcément pas 0 !
    dans ce cas, exposé tel quel, forcément
    essaye de t'en passer avec ça (x <> 0) and (x <= $20).
    c'est de ça que je parlais et d'ailleurs (Pb^<= $20) permet aussi de tester l'utilité de (Pb^ <> $0)
    si tu le fais pas c'est là que "tu vas lire dans un endroit de ta mémoire qui ne t'appartient pas et qui contiendra une valeur aléatoire."

    justement à propos de:
    si la longueur de s est 0, alors s = nil, donc s[1] va lire dans un endroit de ta mémoire qui ne t'appartient pas et qui contiendra une valeur aléatoire.
    c'est pas entièrement vrai
    si S est vide il est claire que tu ne peux pas faire S[1] := #32; == Violation d'accès directe
    sur ça Ok rien à dire

    mais ici @S[1]; pointe sur le premier caractère de la chaine.
    et si S := ''; @S[1]; pointe sur le zéro terminal de cette dernière

    conclusion (Pb^ <> $0) teste si la chaine est vide ou sa fin
    et @S[1] pointe bien sur le zéro terminal si S est une chaine vide.

    Fait le teste ...
    Cordialement,
    @+

  11. #11
    Membre émérite
    Avatar de badaze
    Homme Profil pro
    Chef de projets info
    Inscrit en
    Septembre 2002
    Messages
    1 412
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets info
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2002
    Messages : 1 412
    Points : 2 522
    Points
    2 522
    Par défaut
    Et length(machaine) - length(TrimLeft(machaine)) ça n'irait pas ?
    Cela ne sert à rien d'optimiser quelque chose qui ne fonctionne pas.

    Mon site : www.emmella.fr

    Je recherche le manuel de l'Olivetti Logos 80B.

  12. #12
    Membre éprouvé
    Avatar de Cirec
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    467
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 467
    Points : 1 072
    Points
    1 072
    Par défaut
    Citation Envoyé par badaze Voir le message
    Et length(machaine) - length(TrimLeft(machaine)) ça n'irait pas ?
    je dirais que non
    si on prend cette chaine MaChaine := #32#32#32#32#13#10+' Test';.
    Length(MaChaine) - Length(TrimLeft(MaChaine)) retourne 12
    alors que la bonne réponse est 4

    Cordialement,
    @+

  13. #13
    Membre émérite
    Avatar de badaze
    Homme Profil pro
    Chef de projets info
    Inscrit en
    Septembre 2002
    Messages
    1 412
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets info
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2002
    Messages : 1 412
    Points : 2 522
    Points
    2 522
    Par défaut
    En fait ça donne 7. Ce qui est normal puisque #10 et #13 ne sont pas des espaces. Le résultat est donc correct.

    Nom : Capture20170827_005.JPG
Affichages : 1134
Taille : 29,4 Ko
    Cela ne sert à rien d'optimiser quelque chose qui ne fonctionne pas.

    Mon site : www.emmella.fr

    Je recherche le manuel de l'Olivetti Logos 80B.

  14. #14
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 694
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 694
    Points : 13 130
    Points
    13 130
    Par défaut
    Citation Envoyé par Cirec Voir le message
    mais ici @S[1]; pointe sur le premier caractère de la chaine.
    et si S := ''; @S[1]; pointe sur le zéro terminal de cette dernière

    conclusion (Pb^ <> $0) teste si la chaine est vide ou sa fin
    et @S[1] pointe bien sur le zéro terminal si S est une chaine vide.

    Fait le teste ...
    guillemouze a raison, les chaînes vides sont des pointeurs nil. Le test est très vite fait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    var
      s :string;
    begin
      s := '';
     
      if Assigned(pointer(s))
      then ShowMessage('Assigned')
      else ShowMessage('Not assigned');
    end;
    @S[1] est particulier puisque cela devrait engendrer une VA (S[1] étant invalide). Mais Delphi est sympa, il nous renvoie à nouveau un pointeur nil

    Par contre un transtypage en PChar d'une chaîne vide pointera toujours sur une zone mémoire (initialisée à #0).

  15. #15
    Membre éprouvé
    Avatar de Cirec
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    467
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 467
    Points : 1 072
    Points
    1 072
    Par défaut
    Citation Envoyé par badaze Voir le message
    En fait ça donne 7. Ce qui est normal puisque #10 et #13 ne sont pas des espaces. Le résultat est donc correct.

    Nom : Capture20170827_005.JPG
Affichages : 1134
Taille : 29,4 Ko
    en fait il manque des espaces qui se sont volatilisés lors du coller
    la chaine de départ avait 6 espaces après le retour chariot
    mais toujours est il que la bonne réponse est 4 et non 7 si l'on compte que les espaces (ce qui était demandé au départ)

    les chaînes vides sont des pointeurs nil.
    je ne remets pas cela en cause ...
    que Delphi soit sympa ou non le fait est là
    en faisant @S[1] c'est comme une chaine à zéro terminal que la chaine soit vide ou non on y a accès.
    et si tu fais mon teste tu verras que c'est le cas.

    je comprend que ça puisse dérouter mais ça fonctionne très bien.
    et je n'ai jamais eu de violation d'accès ou autre joyeusetés de ce genre

    Cordialement,
    @+

  16. #16
    Membre émérite
    Avatar de badaze
    Homme Profil pro
    Chef de projets info
    Inscrit en
    Septembre 2002
    Messages
    1 412
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets info
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2002
    Messages : 1 412
    Points : 2 522
    Points
    2 522
    Par défaut
    Citation Envoyé par Cirec Voir le message
    en fait il manque des espaces qui se sont volatilisés lors du coller
    la chaine de départ avait 6 espaces après le retour chariot
    mais toujours est il que la bonne réponse est 4 et non 7 si l'on compte que les espaces (ce qui était demandé au départ)
    Pourquoi ?
    On demande de compter les espaces en début de chaîne (voir aussi le code du message #1) CR et LF ne sont pas des espaces que je sache.
    Cela ne sert à rien d'optimiser quelque chose qui ne fonctionne pas.

    Mon site : www.emmella.fr

    Je recherche le manuel de l'Olivetti Logos 80B.

  17. #17
    Membre éprouvé
    Avatar de Cirec
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    467
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 467
    Points : 1 072
    Points
    1 072
    Par défaut
    Citation Envoyé par badaze Voir le message
    Pourquoi ?
    On demande de compter les espaces en début de chaîne (voir aussi le code du message #1) CR et LF ne sont pas des espaces que je sache.
    tu donnes la réponse !!!
    CR et LF ne sont pas des espaces mais avec ton code ils sont comptés comme tel.
    Ex
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    var
      aStr: string;
    begin
      aStr := '    '{<- 4 espaces}+#13#10+'Test';
      Memo1.Lines.Add(CountLSpace(aStr).ToString); // <--- retourne 4
      Memo1.Lines.Add((length(aStr) - length(TrimLeft(aStr))).ToString); // retourne 6
    end;
    Comme je sens que la question va être posée.
    à savoir:
    Quand est-il des espaces après le retour chariot ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    function CountLSpace(const aStr: string): Integer; inline
    var L: Cardinal;
      PB: PByte;
    begin
      Result := 0;
      PB := @aStr[1];
      L := SizeOf(Char);
      while (Pb^ <> $0) and (Pb^ <= $20) do begin
        if Pb^ = $20 then Inc(Result);
        Inc(Pb, L);
      end;
    end;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
      aStr: string;
    begin
      aStr := '    '{<- 4 espaces}+#13#10+{4 espaces ->}+'    Test';
      Memo1.Lines.Add(CountLSpace(aStr).ToString);  // retourne 8
      Memo1.Lines.Add((length(aStr) - length(TrimLeft(aStr))).ToString);  // retourne 10
    Cordialement,
    @+

  18. #18
    Membre émérite
    Avatar de badaze
    Homme Profil pro
    Chef de projets info
    Inscrit en
    Septembre 2002
    Messages
    1 412
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets info
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2002
    Messages : 1 412
    Points : 2 522
    Points
    2 522
    Par défaut
    En fait je voulais dire : length(machaine) - (length(machaine) - length(TrimLeft(machaine)))
    Cela ne sert à rien d'optimiser quelque chose qui ne fonctionne pas.

    Mon site : www.emmella.fr

    Je recherche le manuel de l'Olivetti Logos 80B.

  19. #19
    Membre éprouvé
    Avatar de Cirec
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    467
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 467
    Points : 1 072
    Points
    1 072
    Par défaut
    Citation Envoyé par badaze Voir le message
    En fait je voulais dire : length(machaine) - (length(machaine) - length(TrimLeft(machaine)))
    euh !!!
    length(machaine) - (length(machaine) - length(TrimLeft(machaine))) == length(TrimLeft(machaine))

    Cordialement,
    @+

  20. #20
    Membre émérite
    Avatar de badaze
    Homme Profil pro
    Chef de projets info
    Inscrit en
    Septembre 2002
    Messages
    1 412
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets info
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2002
    Messages : 1 412
    Points : 2 522
    Points
    2 522
    Par défaut
    Bon. Une tisane ou une camomille et hop au dodo le badaze !


    Dans mon second message j'avais compté 5 espaces alors qu'il n'y en avait que 4 ce qui fait que j'ai compté 12 caractères au lieu de 11. D'où ma confusion quand j'ai vu 7 comme résultat => 12 - 5 = 7 (ce qui donne #13#10_Test)
    Cela ne sert à rien d'optimiser quelque chose qui ne fonctionne pas.

    Mon site : www.emmella.fr

    Je recherche le manuel de l'Olivetti Logos 80B.

Discussions similaires

  1. Réponses: 28
    Dernier message: 11/10/2006, 22h36
  2. Compter le nombre de page d'un report
    Par ToYonos dans le forum C++Builder
    Réponses: 4
    Dernier message: 17/06/2003, 09h36
  3. compter le nombre de record
    Par pram dans le forum XMLRAD
    Réponses: 2
    Dernier message: 12/03/2003, 09h53
  4. [TListView] Compter le nombre de lignes
    Par agh dans le forum Composants VCL
    Réponses: 2
    Dernier message: 30/09/2002, 20h25
  5. Compter le nombre ligne listée (COUNT) ?
    Par StouffR dans le forum Langage SQL
    Réponses: 7
    Dernier message: 02/09/2002, 09h41

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