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

Delphi Discussion :

Récupérer chaque chaine séparé par un séparateur


Sujet :

Delphi

  1. #1
    Membre habitué

    Inscrit en
    Février 2005
    Messages
    356
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 356
    Points : 175
    Points
    175
    Par défaut Récupérer chaque chaine séparé par un séparateur
    Bonjour tout le monde !

    Voila, j'ai des paramètres enregistré dans un fichier et ces différents paramètres sont séparé par une ,
    - De quel façon puis-je les récupérer ?

    => Exemple de chaîne : adsl, debit , ping,upload,download (petit piège, il peut y avoir des espaces)

    => J'aimerais savoir comment récupéré ces champs ?

    Info : J'aimerais bien y accéder de la façon suivante :

    InfoParametre[0] = 'adsl';
    InfoParametre[1] = 'debit';
    InfoParametre[2] = 'ping';
    ...

    EDIT : Je sais récupéré la chaîne dans le fichier, il me reste plus qu'à la décomposer

    Merci de vos réponses

  2. #2
    Rédacteur
    Avatar de Pedro
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    5 411
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 5 411
    Points : 8 078
    Points
    8 078
    Par défaut
    Salut

    Utilise Pos et PosEx pour avoir la position du caractère que tu cherches (ici en l'occurrence, une virgule) et après, Copy pour copier la bonne partie de la chaîne.
    Tu peux ensuite utiliser Trim pour enlever les espaces.

    Pour plus d'infos,

  3. #3
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 737
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 : 13 737
    Points : 25 654
    Points
    25 654
    Par défaut
    Essaye de Voir une TStringList avec CommaText, peut-être un soucis avec les espaces, sinon, va sur Phidels, j'y ai mis une fonction Explode qui fera la découpe dans un tableau, comme tu le souhaite justement ... plus j'ai de monde qu'il l'utilise pour j'aurais des retours sur des cas d'utilisation que je n'avais pas prévu, mais pour ta demande, elle fonctionne a merveille, je l'utilise pour découper un numéro de version par exemple

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    1.4.2.17
    [0] = 1
    [1] = 4
    [2] = 2
    [3] = 17
    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
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    {* -----------------------------------------------------------------------------
    la fonction Explode retourne un tableau de chaînes. Ce sont les sous-chaînes, extraites de S, en utilisant le séparateur Separator. cela peut servir pour lire du CSV
    @param S Chaine à découper
    @param A Tableau de Chaine qui recevra la découpe
    @param Separators Caractères qui délimitent une chaine pour la découpe
    @param ExcludeEmpty Si True, les Chaines vides ne sont pas insérés dans le Tableau
    @param Quotes Caractères qui délimitent une chaine pour la découpe contenant des Separators, n'importe quel séparateur peut commencer et terminé une chaine, une quote doublée est considéré comme valeur un quote dans la chaine
    @param KeepSeparators Si True, A contient les chaines et les séparateurs mais pas les Quotes, sinon (par défaut) A ne contient que les Chaines.
    @return Nombre de Séparateur Trouvé (peut-être différent du nombre de chaine dans A !)
    ------------------------------------------------------------------------------ }
    function Explode(const S: string; out A: Types.TStringDynArray; const Separators: string; ExcludeEmpty: Boolean = False; const Quotes: string = ''; KeepSeparators: Boolean = False): Integer;
    var
      iLesSep: Integer;
      iLesQuote: Integer;
     
      function IsSeparator(C: Char): Integer;
      begin
        for Result := 1 to iLesSep do
          if C = Separators[Result] then
            Exit;
     
        Result := -1;
      end;
     
      function IsQuote(C: Char): Integer;
      begin
        for Result := 1 to iLesQuote do
          if C = Quotes[Result] then
            Exit;
     
        Result := -1;
      end;
     
    var
      iStr: Integer;
      iQuote: Integer;
      iLenS: Integer;
      iLenSS: Integer;
      iLenA: Integer;
      iAdded: Integer;
      iBegin: Integer;
      Quoted: Boolean;
      DoubleQuoted: Boolean;
      AlreadyDQ: Boolean;
      QuoteConcat: string;
      iOffQuote: Integer;
      LastIsSep: Boolean;
    begin
      iLenS := Length(S);
      iLesSep := Length(Separators);
     
      if (iLenS = 0) or (iLesSep = 0) then
      begin
        SetLength(A, 1);
        Result := 0;
        A[Result] := '';
        Exit;
      end;
     
      iLesQuote := Length(Quotes);
      for iQuote := 1 to iLesQuote do
        if IsSeparator(Quotes[iQuote]) > 0 then
          raise EParserError.CreateFmt('le Délimiteur "%s" ne peut pas être un Séparateur !', [Quotes[iQuote]]);
     
      Result := 0;
      iQuote := 0;
      for iStr := 1 to Length(S) do
      begin
        if IsSeparator(S[iStr]) > 0 then
          Inc(Result)
        else
          if IsQuote(S[iStr]) > 0 then
            Inc(iQuote);
      end;
     
      if Odd(iQuote) then
        raise EParserError.CreateFmt('Nombre de Délimiteur Incorrect : "%d" !', [iQuote]);
     
      LastIsSep := IsSeparator(S[iLenS]) > 0;
     
      if KeepSeparators then
        iLenA := Result * 2 + 1
      else
        iLenA := Result + 1;
      SetLength(A, iLenA);
      iLenSS := 0;
      iAdded := 0;
      Quoted := False;
      iOffQuote := 0;
      QuoteConcat := '';
      AlreadyDQ := False;
      iBegin := 1;
      if IsSeparator(S[1]) > 0 then
      begin
        if KeepSeparators then
        begin
          iBegin := 2;
          A[iAdded] := S[1];
          Inc(iAdded);
        end;
      end;
     
      for iStr := iBegin to iLenS do
      begin
        if not Quoted and (IsSeparator(S[iStr]) > 0) then
        begin
          if ExcludeEmpty and (iLenSS = 0) then
          begin
            if KeepSeparators then
            begin
              A[iAdded] := S[iStr];
              Inc(iAdded);
            end;
            iBegin := iStr + 1;
          end else
          begin
            if AlreadyDQ then
              A[iAdded] := QuoteConcat
            else
              A[iAdded] := Copy(S, iBegin, iLenSS);
     
            AlreadyDQ := False;
            Inc(iAdded);
     
            if KeepSeparators and (iBegin > 0) then
            begin
              A[iAdded] := S[iStr];
              Inc(iAdded);
            end else
              begin
              if LastIsSep and KeepSeparators and (iStr = iLenS) then
              begin
                A[iAdded] := S[iStr];
                Inc(iAdded);
              end;
            end;
            iBegin := iStr + 1;
            iLenSS := 0;
          end;
        end else
        begin
          if IsQuote(S[iStr]) > 0 then
          begin
            if Quoted then
            begin
              Quoted := False;
              if iStr < iLenS then
              begin
                DoubleQuoted := IsQuote(S[iStr+1]) > 0;
                if AlreadyDQ then
                  QuoteConcat := QuoteConcat + Copy(S, iBegin, iLenSS) + IfThen(DoubleQuoted, S[iStr+1], '')
                else
                  QuoteConcat := Copy(S, iBegin, iLenSS) + IfThen(DoubleQuoted, S[iStr+1], '');
                AlreadyDQ := AlreadyDQ or DoubleQuoted;
              end;
            end else
            begin
              Quoted := True;
              iBegin := iStr + 1;
              iLenSS := 0;
            end;
          end else
          begin
            if Quoted and (IsSeparator(S[iStr]) > 0) then
              Inc(iOffQuote);
            Inc(iLenSS);
          end;
        end;
      end;
     
      if iBegin <= iLenS then
      begin
        A[iAdded] := Copy(S, iBegin, MaxInt);
        Inc(iAdded);
     
        if LastIsSep and KeepSeparators then
        begin
          A[iAdded] := S[iLenS];
          Inc(iAdded);
        end;
      end;
     
      if LastIsSep and not ExcludeEmpty then
        Inc(iAdded);
     
      if iAdded < iLenA then
        A := Copy(A, 0, iAdded);
     
      Result := Result - iOffQuote;
    end;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    var
    InfoParametre: Types.TStringDynArray;
    begin
      Explode(Chaine, InfoParametre, ',');
      InfoParametre[0] = 'adsl';
      InfoParametre[1] = 'debit';
      InfoParametre[2] = 'ping';
    end;

  4. #4
    Membre habitué

    Inscrit en
    Février 2005
    Messages
    356
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 356
    Points : 175
    Points
    175
    Par défaut
    Ok, merci de vos réponses.

    Pour ShaiLeTroll, je vais essayer ça tout de suite. (et consulter ton code)

    Pour Pedro, la fonction va me retourné un indice. Dans le cas où j'ai 4 paramètres, j'ai trois virgule.
    => Donc la méthode est un peu plus galère, je pense.

  5. #5
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 737
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 : 13 737
    Points : 25 654
    Points
    25 654
    Par défaut
    Le Coup classique, tu rajoute une virgule à la fin si tu ne veux pas gérer l'arrivée à la fin de chaine, et avec une boucle, tu alimente un tableau avec un copy, ...

    je te conseille de le faire avec PosEx (avec Pos, il y a plus de manipulation de la chaine, cela nuit au perf), au moins une fois, pour l'entrainement, c'est des algos de base, qu'il est bon de savoir faire ... ça peut aider pour d'autres problématiques, ...

  6. #6
    Rédacteur
    Avatar de Pedro
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    5 411
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 5 411
    Points : 8 078
    Points
    8 078
    Par défaut
    Citation Envoyé par pepito62
    Pour Pedro, la fonction va me retourné un indice. Dans le cas où j'ai 4 paramètres, j'ai trois virgule.
    => Donc la méthode est un peu plus galère, je pense.
    Non pas tant que ça si c'est bien réfléchi

  7. #7
    Membre habitué

    Inscrit en
    Février 2005
    Messages
    356
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 356
    Points : 175
    Points
    175
    Par défaut CODE pas QUOTE
    Je n'ai pas la méthode PosEx.

    Y a t-il une classe a inclure ???

    Sinon pour ShaiLeTroll, ta fonction est super longue !!!

    Je compte faire un bout d'algo moi-même, qui donnerait par exemple :
    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
    procedure TForm1.Button1Click(Sender: TObject);
    var InfoParametre: ......... ?
    var i,j : integer;
    var chaine,chainetmp : string;
    begin
      j := 1;
      Edit1.Text := 'debit, adsl,voiture, tomate  ,avion,voiture';
      chaine := trim(Edit1.Text);
      for i :=1 to length(chaine) do
      begin
        if chaine[i] <> ',' then
          InfoParametre[j] := InfoParametre[j] + chaine[i]
        else
          j := j + 1;
      end;
      showmessage(InfoParametre[j]);
    end;
    Comment puis-je déclarer un tableau de chaine ???? (sa taille sera dynamique bien sur)

    MERCI BCP

  8. #8
    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
    On peut utiliser CommaSeparatedToStringlist

  9. #9
    Rédacteur
    Avatar de Pedro
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    5 411
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 5 411
    Points : 8 078
    Points
    8 078
    Par défaut
    Citation Envoyé par pepito62
    Je n'ai pas la méthode PosEx.
    Quelle version de Delphi utilises-tu?

  10. #10
    Rédacteur/Modérateur
    Avatar de ero-sennin
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2005
    Messages
    2 965
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Nord (Nord Pas de Calais)

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

    Informations forums :
    Inscription : Juillet 2005
    Messages : 2 965
    Points : 4 935
    Points
    4 935
    Par défaut
    Salut,

    Comment puis-je déclarer un tableau de chaine ???? (sa taille sera dynamique bien sur)
    Comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    //Déclaration du Tableau :
    MonTableau:array of string;
     
    //Initialisation
    SetLength(MonTableau,0);
     
    //Si tu ajoute un élément:
    SetLength(MonTableau,1);

  11. #11
    Rédacteur
    Avatar de Pedro
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    5 411
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 5 411
    Points : 8 078
    Points
    8 078
    Par défaut
    Citation Envoyé par ero-sennin
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    //Si tu ajoute un élément:
    SetLength(MonTableau,1);
    "Si tu n'as qu'un seul élément" serait plus juste

  12. #12
    Membre habitué

    Inscrit en
    Février 2005
    Messages
    356
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 356
    Points : 175
    Points
    175
    Par défaut
    J'ai la version 6.

    Sinon, je pense que je peux utiliser un TSTringList dans mon exemple.

    - Comment dois-je déclarer ma variable ?
    - Comment dois-je l'initialiser ?
    - Comment on l'affecte ?

    Merci bcp

  13. #13
    Membre habitué

    Inscrit en
    Février 2005
    Messages
    356
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 356
    Points : 175
    Points
    175
    Par défaut
    C'est bon, je viens de trouvé comment faire.

    Merci pour vos conseils quand même.

    Voici mon petit algo
    procedure TForm1.Button1Click(Sender: TObject);
    var InfoParametre : TStringList;
    var i : integer;
    var chaine,chainetmp : string;
    begin
    InfoParametre := TStringList.Create;
    Edit1.Text := 'debit, adsl,voiture, tomate ,avion,voiture';
    chaine := Edit1.Text;
    for i :=1 to length(chaine) do
    begin
    if chaine[i] <> ',' then
    chainetmp := chainetmp + chaine[i]
    else
    begin
    InfoParametre.Add(trim(chainetmp));
    chainetmp := '';
    end;
    end;
    Edit2.Text :=InfoParametre.Strings[3];
    InfoParametre.Free;
    end;

  14. #14
    Membre habitué

    Inscrit en
    Février 2005
    Messages
    356
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 356
    Points : 175
    Points
    175
    Par défaut
    Je vais optimiser un peu tout ça maintenant. MERCI @tous

  15. #15
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 737
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 : 13 737
    Points : 25 654
    Points
    25 654
    Par défaut
    Delphi 6, pas de PoxEx ? Mais oui, dans mon programme à Bordel j'ai 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
    29
    30
    31
    32
    {$IFDEF VER140} // Delphi 6 - A Partir de Delphi 7, fonction StrUtils.PosEx
       function PosEx(const SubStr, S: string; Offset: Cardinal = 1): Integer;
       var
          I, X: Integer;
          Len, LenSubStr: Integer;
       begin
          if Offset = 1 then
             Result := Pos(SubStr, S)
          else
          begin
             I := Offset;
             LenSubStr := Length(SubStr);
             Len := Length(S) - LenSubStr + 1;
             while I <= Len do
             begin
                if S[I] = SubStr[1] then
                begin
                   X := 1;
                   while (X < LenSubStr) and (S[I + X] = SubStr[X + 1]) do
                      Inc(X);
                   if (X = LenSubStr) then
                   begin
                      Result := I;
                      exit;
                   end;
                end;
                Inc(I);
             end;
             Result := 0;
          end;
       end;
    {$ENDIF}
    Sinon, Explode est super longue parce que cela gère presque trop de chose, comme le découpage de CSV ...

    tient, j'ai fait une version de explode avec Delete et je viens de faire avec PosEx, par Delete/Copy c'est 3 fois plus lent, et 2.5 par PosEx, ma fonction explode est codé pour un maximum de perf (du moins la version originale avec moins de paramètre, mais celle-ci reste la plus rapide sans ASM que j'ai pu testé ...)

    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
    procedure ExplodeByCopy(Chaine: string; out Liste : Types.TStringDynArray; Delimiteur: char);
    var
      iPos: Integer;
    begin
       SetLength(Liste, 0);
       iPos := Pos(Delimiteur, Chaine);
       while iPos > 0 do
       begin
          if iPos <> 1 then
          begin
            SetLength(Liste, Length(Liste) + 1);
            Liste[High(Liste)] := Copy(Chaine, 1, iPos - 1);
          end;
          Delete(Chaine, 1, iPos);
          iPos := Pos(Delimiteur, Chaine);
       end;
       if Chaine <> '' then
       begin
         SetLength(Liste, Length(Liste) + 1);
         Liste[High(Liste)] := Chaine;
       end;
    end;
    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
    procedure ExplodeByPosEx(Chaine: string; out Liste : Types.TStringDynArray; Delimiteur: char);
    var
      iPos, iBegin: Integer;
    begin
       SetLength(Liste, 0);
       iPos := Pos(Delimiteur, Chaine);
       iBegin := 1;
       while iPos >= iBegin do
       begin
         SetLength(Liste, Length(Liste) + 1);
         Liste[High(Liste)] := Copy(Chaine, iBegin, iPos - iBegin);
         iBegin := iPos + 1;
         iPos := PosEx(Delimiteur, Chaine, iBegin);
       end;
       if iBegin <= Length(Chaine) then
       begin
         SetLength(Liste, Length(Liste) + 1);
         Liste[High(Liste)] := Copy(Chaine, iBegin, MaxInt);
       end;
    end;

  16. #16
    Modérateur
    Avatar de Rayek
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2005
    Messages
    5 235
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Haute Savoie (Rhône Alpes)

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

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 235
    Points : 8 504
    Points
    8 504
    Par défaut
    Mon dieu, que c'est bine compliquer tout cela

    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
     
    function DecoupeList(MaChaine,separateur : String) : String;
    Var
     
      lst : TStringList;
    begin
      Result := '';
      lst := TStringList.Create;
      try
        lst.text := MaChaine;
        lst.text := StringReplace(lst.text,separateur,#13#10,[rfReplaceAll]);
        Result := lst.text;
      finally
        lst.free;
      end;
    end;
    après il te suffit d'appeler la fonction

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    var
      UneList : TStringList;
    begin
       UneList := TStringList.Create;
      try
        UneList.text := DecoupeList('adsl, debit , ping,upload,download',',');
        Showmessage('Adsl : ' + UneList[0]);
        ShowMessage('debit : ' + UneList[1]);
        //etc...
      finally
        UneList.free;
      end;
    end;
    Et je pense qu'on peut encore simplifier ce code

  17. #17
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    624
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 624
    Points : 754
    Points
    754
    Par défaut
    Dans ce cas la, consulter ici, il y a aussi ma fonction Explode, rapide, concise et performante.

    La solution avec la StringGrid est tout de même la plus élégante.

  18. #18
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 737
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 : 13 737
    Points : 25 654
    Points
    25 654
    Par défaut
    Citation Envoyé par Malatar
    Mon dieu, que c'est bine compliquer tout cela
    Quand tu as des fichiers d'une bonne centaine de Mo a analyser, le découpage par TStringList (qui peut donner un résultat incorrect, j'ai oublié le cas ...) te pèses en performance, mais t'inquiète, je l'ai aussi cette variante, c'est la base, mais tellement moins intéressante ...

    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
     
    procedure StringToList(Str: string; Sep: Char; List: TStrings);
    begin
       if Assigned(List) then
       begin
          Str := Trim(Str);
          ReplaceChar(Str, Sep, #10);
          List.Text := Str;
       end;
    end;
     
    procedure ReplaceChar(var S: string; const OldChar, NewChar: Char);
    var
      i: Integer;
    begin
       if OldChar = NewChar then Exit;
       for i := 1 to Length(S) do
          if S[i] = OldChar then
            S[i] := NewChar;
       end;
    end;
    Sinon, pour la Fonction Explode de "Fabrice ROUXEL 1", pensez a corriger "if (txt[i] = ' ') then" en "if (txt[i] = delimit) then", bien sur,

    sinon, sur ce sujet, j'avais déjà ramené ma fraise, ... d'ailleurs, j'ai mis à jour "ReduceStr", qui pouvait poser des problèmes pour la conversion en PChar (affichage dans un compo windows par exemple)

    D'ailleurs Fabrice ROUXEL, ta fonction explode est sympa, tu devrais utiliser le type Delphi standard, et les setlength, c'est ce qu'il y a de plus couteux, mes fonctions semblent souvent plus "complexes" car je précalcule le nombre d'item, pour ta fonction, cela diviserai quasiment les temps par deux, ...

  19. #19
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    624
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 624
    Points : 754
    Points
    754
    Par défaut
    pensez a corriger "if (txt[i] = ' ') then" en "if (txt[i] = delimit) then
    C'est fait (Le delimiteur recherché était l'espace dans le thread précédent d'où la confusion).

    tu devrais utiliser le type Delphi standard, et les setlength, c'est ce qu'il y a de plus couteux
    Oui c'est vrai, mais sous Delphi5, par exemple, le type TStringDynArray n'existe pas.
    Disons que la fonction est compatible Delphi5

    le découpage par TStringList (qui peut donner un résultat incorrect, j'ai oublié le cas ...) te pèses en performance
    Encore vrai et ma fonction est plus performante.
    (J'ai un fichier de 100 000 lignes pour les tests)

    je précalcule le nombre d'item, pour ta fonction, cela diviserai quasiment les temps par deux, ...
    Ok, je teste.

  20. #20
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 737
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 : 13 737
    Points : 25 654
    Points
    25 654
    Par défaut
    Ah, D5, oui, j'ai bossé en D3 à D7, j'ai pris le courage de corriger les types, qui n'existait pas, heureusement, j'ai défini ce genre de types stantard dans CustomTypes.pas ^_^

    Mon Test de temps c'est
    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
       for k := 1 to 10 do
       begin
          QueryPerformanceCounter(StartTick);
          try
             for i := 1 to 1000 do
             begin
                Explode(Value, StrArray, ';');
             end;
          finally
             QueryPerformanceCounter(EndTick);
             QueryPerformanceFrequency(TickPerSec);
             TimeIteration := Round((EndTick - StartTick) / TickPerSec * 1000);
             MemoTimes.Lines.Add('Explode Basique N°' + IntToStr(k) + ' : ' + IntToStr(TimeIteration) + ' ms');
          end;
       end;
       ListBoxWord.Items.Add('--------------------'); ListBoxWord.Items.Add('Explode Basique');
       for iStr := Low(StrArray) to High(StrArray) do
         ListBoxWord.Items.Add(StrArray[iStr]);
    sinon Fabrice, je pense, qu'au final, tu auras une fonction qui ressemble comme deux gouttes d'eau à celle-ci, qui est la version optimisé (que j'ai repondu pour le forum, je ne l'avais plus) de Explode avant d'y rajouter les paramètres pour le csv ou la gestion du multi séparateur comme me l'avait demandé un collègue ...

    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
    function ExplodeLazy(const S: string; out A: Types.TStringDynArray; Separator: Char): Integer;
    var
      I, J, K: integer;
      iLenS: integer;
    begin
      iLenS := Length(S);
     
      if iLenS = 0 then
      begin
        SetLength(A, 1);
        Result := 0;
        A[Result] := '';
        Exit;
      end;
     
      Result := 0;
      for I := 1 to iLenS do
        if S[I] = Separator then
          Inc(Result);
     
      if S[iLenS] = Separator then
        SetLength(A, Result)
      else
        SetLength(A, Result + 1);
     
      K := 1;
      J := 0;
      for I := 1 to iLenS do
        if S[I] = Separator then
        begin
          if K <> I then
            A[J] := Copy(S, K, I - K);
     
          Inc(J);
          K := I + 1;
        end;
      if K <= iLenS then
        A[J] := Copy(S, K, MaxInt);
    end;
    car a part, le SetLength, et les noms des variables c'est exactement le même algo, difficile d'inventer la roue à chaque fois !
    Sinon corrige "deb := i;" en "deb := i + ;" car on chope le ; dans l'item suivant ...,

    0;1;2!2;333;44!44;55555;666!666;7777777;8888!8888;999999999;00000!00000;"AAA";"BBB";"CCC"
    ->
    '0', ';1', ';2!2', ... au lieu de '0', '1', '2!2', ...



    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
    function ExplodeFabriceRouxel(txt: string; delimit: char): TStringDynArray;
    var
      i: integer;
      deb: integer;
      idx: integer;
    begin
      i := 1;
      deb := 1;
      idx := 0;
      txt := Trim(txt);
      SetLength(Result,0);
      while (i < length(txt)) do
      begin
        if (txt[i] = delimit) then
        begin
          SetLength(Result, idx +1);
          Result[idx] := copy(txt, deb, i - deb);
          deb := i;
          inc(idx);
        end;
        inc(i);
      end;
      if i <> deb then
      begin
        SetLength(Result, idx +1);
        Result[idx] := copy(txt, deb, length(txt));
      end;
    end;

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Réponses: 5
    Dernier message: 24/02/2011, 16h21
  2. Découper une chaine séparée par des séparateur ;
    Par d.tellier dans le forum MS SQL Server
    Réponses: 9
    Dernier message: 23/12/2010, 19h21
  3. récupérer des mots séparés par un espace dans une ligne
    Par laurentze dans le forum Shell et commandes GNU
    Réponses: 2
    Dernier message: 14/06/2010, 17h04
  4. Récupérer des mots séparés par un espace dans un .txt
    Par elnino67 dans le forum Débuter
    Réponses: 2
    Dernier message: 28/05/2008, 23h13
  5. Comment récupérer des valeur séparé par ; ?
    Par Nico128 dans le forum Delphi
    Réponses: 12
    Dernier message: 14/01/2007, 13h42

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