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 :

Précisions sur les pointeurs @ et ^ (arobas et circonflexe)


Sujet :

Langage Delphi

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    322
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Janvier 2009
    Messages : 322
    Points : 310
    Points
    310
    Par défaut Précisions sur les pointeurs @ et ^ (arobas et circonflexe)
    Bonjour a tous

    J'ai toujours vue le @ avant une variable.
    Mais le ^ est parfois avant parfois après la variable.

    Qu'elle est la différence et comment emploie-t-on @ et ^?

    Merci d'avance

  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 : 55
    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 sgmsg Voir le message
    Bonjour a tous

    J'ai toujours vue le @ avant une variable.
    Mais le ^ est parfois avant parfois après la variable.

    Qu'elle est la différence et comment emploie-t-on @ et ^?

    Merci d'avance
    @ est un raccourci pour la function Addr(), donc là pas de problème je pense.
    ^ est utilisé de deux façon par contre :
    - après un pointeur pour atteindre la destination (ce qui se note "v->" en C se note "v^" en Pascal).
    - devant un type pour déclarer un pointeur vers ce type (ce qui se note "char*" en C se note "^char" en Pascal)

    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
     
    type
      PInteger = ^Integer; // pointeur vers un Integer
    var
      p1: PInteger; // variable de type pointeur vers un Integer
      p2: ^Integer; // idem
      i : Integer; // Integer statique
      j : Integer; // un autre entier 
      k : array[1..6] of Integer; // un tableau de 6 entiers
    begin
      p1 := Addr(i); // p1 pointe sur i
      p2 := @i; // idem pour p2
      p1^ := 1; // donne à i la valeur 1
      Inc(p2^); // incrément i
      Inc(p2); // décale le pointeur de la taille de son type
      // en théorie p2 pointe donc maintenant sur j
      // mais rien ne le garantie !
      // par contre ça fonctionne très bien sur un tableau, record...
      // pour lesquelles l'organisation mémoire est connue
      p2 := @k; // pointe sur le premier élément de k
      p2^ := 1; // lui donne la valeur 1
      Inc(p2); // passe au deuxième élément de k
      Inc(p2, 2); // passe au 4ième (2ième + 2)
      p2^ := 5; // équivalent à k[4] := 5;
    end;
    NB: dans l'exemple ci-dessus, si k était un tableau dynamique @k donnerait l'adresse d'un pointeur vers le tableau et non l'adresse du premier élément qu'on peut atteindre par @k[0]

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    322
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Janvier 2009
    Messages : 322
    Points : 310
    Points
    310
    Par défaut
    Merci Paul

    J'ai tout compris ou presque :

    J'essaie de recréer en partie du code que François Piette avait déjà donné pour transférer le contenu d'un string dans un autre ultrarapide et efficace, (dont j'efface un certain caractère si présent)

    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
    function Efface(const Source:ansistring; const ceci:ansichar):ansistring;
    var s,d,d0:^ansichar;
        ls:integer;
    begin
        ls:=length(Source);
        SetLength(result,ls);
        d0:=@result[1];//pointe sur le premier élément
        d :=d0;
        for s := @source[1] to @source[1]+ls-1 do //Erreur la variable de contrôle de boucle FOR doit être de type ordinal
            if s^<>ceci then begin//contenu pointer par s <> ceci alors
                inc(d);//pointe sur le prochain élément
                d^:=s^;//transfert l’élément
            end;
        setlength(result,d-d0);//redimensionne à la bonne dimension
    end;
    Y'a-t'il moyen de balayer la variable "Source" en incrémentant un pointeur?

  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 : 55
    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
    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
     
    function Efface(const Source:ansistring; const ceci:ansichar):ansistring;
    var s,d,d0:^ansichar;
        i,j,ls:integer;
    begin
        ls:=length(Source);
        SetLength(result,ls);
        d0:=@result[1];//pointe sur le premier élément
        d :=d0;
        s := @source[1];
        j := 0;
        for i := 0 to ls-1 do // for sur un entier
        begin
            if s^<>ceci then begin//contenu pointer par s <> ceci alors
                inc(d);//pointe sur le prochain élément
                d^:=s^;//transfert l’élément
                inc(j);
            end;
            inc(s); // incrémenter s (comme tu voulais le faire dans le for)
        end;
        setlength(result,j);//redimensionne à la bonne dimension
    // d-d0 pourrait être utilisé sous la forme Integer(d) - Integer(d0)
    // mais sous XE2 il faut utiliser NativeInt...il est plus simple d'utiliser "j"
    end;

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    322
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Janvier 2009
    Messages : 322
    Points : 310
    Points
    310
    Par défaut
    Merci beaucoup Paul

    L'algo original avait une faute...
    Voici donc corriger en incluant ta suggestion

    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
     
    (* Révision du code *)
    function Efface(const Source:ansistring; const ceci:ansichar):ansistring;
    var s,d,d0:^ansichar;
        i,ls:integer;
    begin
        ls:=length(Source);
        SetLength(result,ls);
        d0:=@result[1];//pointe sur le premier élément
        d :=d0;
        s := @source[1];
        for i := 0 to ls-1 do begin// for sur un entier
            if s^<>ceci then begin//contenu pointer par s <> ceci alors
    (* Erreur il fallait intervertir les deux lignes suivantes mea culpa *)
                d^:=s^;//transfert l’élément
                inc(d);//pointe sur le prochain élément
    (* Fin de l'erreur *)
            end;
            inc(s); // incrémenter s (comme tu voulais le faire dans le for)
        end;
        setlength(result,NativeInt(d)-NativeInt(d0));//redimensionne à la bonne dimension tel que tu l'as signalé
    //je préfère cette solution à l'incrémentation de j pour des raisons d'optimisation
    end;
    Est-ce qu'il y a moyen d'optimiser la routine?

    Est que remplacer l'appel de la fonction par une procédure

    soit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    procedure Efface(const Source:ansistring; var result:string; const ceci:ansichar):ansistring;
    donnerait des gains significatifs ?

    Autrement dit : Est-ce qu'avec function le résultat doit être recopier une fois la routine effectué ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
        s:=Efface(s, 'A'):
    Ou simplement c'est le pointeur de la variable qui pointe maintenant dans une autre zone mémoire ?

    Ce qui donnerait dans les faits le même temps d'exécution pour la procédure

    Merci encore

  6. #6
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 577
    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 577
    Points : 25 225
    Points
    25 225
    Par défaut
    Si tu veux jouer à la performance extrème, on a déjà pas mal débattu pour une fonction similaire : Remplacement d'occurence de caractères ou Comment supprimer tous les caractères spéciaux d'une string ?



    Le Dernier SetLength de Reduction sous D7, c'était extrément couteux !
    En D2007 ou avec FastMM, c'est 100 fois plus rapide
    En DXE2, avec l'UNICODE, je ne me lancerais plus dans ce genre de chose, bon semble ne gérer que le AnsiString, pense des affections entre String et AnsiString sous XE2, c'est réallocation et traduction en fonction du CodePage !

    Donc mettre un string en var, ça ne passera pas du tout !

    Pour la différence de performance entre procedure var et function, euh, ça m'intéresse, le result, je ne sais pas trop comme ça fonctionne
    A part que le Result c'est sur le Registre EAX pour les entiers et pointeurs, tout en se rappelant que EAX contient aussi le 1er paramètre !
    Ce qui en ASM permet de faire deux trois trucs sympa !



    Pour D7, j'avais osé ceci (je ne l'ai testé qu'avec les variables locales)
    Cela fonctionnait, comme le FreeMem n'indiquait pas la longueur à libérer, il n'y avait pas de soucis !
    Bon, je l'ai juste pour le fun, jamais osé le faire en prod !

    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 ReduceStr(var S: string; NewLength: Integer);
    type
       PStrRec = ^StrRec;
       StrRec = packed record
          refCnt: Longint;
          length: Longint;
       end;
    var
      SMeta: PStrRec;
    begin
       SMeta := PStrRec(Integer(S) - SizeOf(StrRec));
       if SMeta.refCnt < 0 then
       begin
         if NewLength < Length(S) then
         begin
           S[Succ(NewLength)] := #0;
           SMeta.length := NewLength;
         end;
       end
       else
         SetLength(S, NewLength); 
    end;

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    322
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Janvier 2009
    Messages : 322
    Points : 310
    Points
    310
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    Si tu veux jouer à la performance extrème, on a déjà pas mal débattu pour une fonction similaire : Remplacement d'occurence de caractères ou Comment supprimer tous les caractères spéciaux d'une string ?

    Le Dernier SetLength de Reduction sous D7, c'était extrément couteux !
    En D2007 ou avec FastMM, c'est 100 fois plus rapide
    En DXE2, avec l'UNICODE, je ne me lancerais plus dans ce genre de chose, bon semble ne gérer que le AnsiString, pense des affections entre String et AnsiString sous XE2, c'est réallocation et traduction en fonction du CodePage !

    Donc mettre un string en var, ça ne passera pas du tout !

    Pour la différence de performance entre procedure var et function, euh, ça m'intéresse, le result, je ne sais pas trop comme ça fonctionne
    A part que le Result c'est sur le Registre EAX pour les entiers et pointeurs, tout en se rappelant que EAX contient aussi le 1er paramètre !
    Ce qui en ASM permet de faire deux trois trucs sympa !
    Merci pour les liens

    Si j'obtiens quelque chose différent significativement intéressant je fais signe

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    322
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Janvier 2009
    Messages : 322
    Points : 310
    Points
    310
    Par défaut
    Si ça peut intéresser des gens

    Voici les résultats de plusieurs routines exécutées 16 fois sur la chaine résultante

    Longueur initiale de la chaine: 268435456 caractères

    Procédure________Durée(s)_______Longueur finale de la chaîne
    StringReplace_____00:05:293_____268435424
    Efface___________00:17:743_____233832448
    Efface0__________00:18:758_____233832448
    Efface1__________00:15:224_____233832448<-Championne
    Efface2__________00:17:671_____233832448
    Efface3__________00:17:682_____233832448

    Conclusion :
    1 - La boucle Pour(For) est pénalisante dans ce cas d'espèce
    2 - Affecter une variable de travaille est pénalisant aussi bien en result qu'en paramètre
    3 - Vaut mieux travailler directement dans la chaine que dans une copie (tiré de 2)
    4 - StringReplace ne permet pas d'effacer une chaine sans laisser de trace

    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
     
    function Efface0(const Source:ansistring; const ceci:ansichar):ansistring;
    var s,d,d0:^ansichar;
        i,ls:integer;
    begin
        ls:=length(Source);
        SetLength(result,ls);
        d0:=@result[1];//pointe sur le premier élément
        d :=d0;
        s := @source[1];
        for i := 0 to ls-1 do begin// for sur un entier
            if s^<>ceci then begin//contenu pointer par s <> ceci alors
                d^:=s^;//transfert l’élément
                inc(d);//pointe sur le prochain élément
            end;
            inc(s); // incrémenter s (comme tu voulais le faire dans le for)
        end;
        setlength(result,NativeInt(d)-NativeInt(d0){j});//redimensionne à la bonne dimension
    end;
     
    function Efface2(const Source:ansistring; const ceci:ansichar):ansistring;
    var s,sf,d,d0:^ansichar;
        i,ls,ld:integer;
    begin
        ls:=length(Source);
        SetLength(result,ls);
        d0:=@result[1];//pointe sur le premier élément
        d :=d0;
        s:=@source[1];//pointe sur le premier élément
        sf:=@source[ls];
        inc(sf);
        while s<>sf do begin// sur un entier
            if s^<>ceci then begin//contenu pointer par s <> ceci alors
                d^:=s^;//transfert l’élément
                inc(d);//pointe sur le prochain élément
            end;
            inc(s); // incrémenter s (comme tu voulais le faire dans le for)
        end;
        setlength(result,NativeInt(d)-NativeInt(d0){j});//redimensionne à la bonne dimension
        //result:=ls-ld;
    end;
     
    procedure Efface3(const Source:ansistring;var result:ansistring; const ceci:ansichar);
    var s,sf,d,d0:^ansichar;
        i,ls,ld:integer;
    begin
        ls:=length(Source);
        SetLength(result,ls);
        d0:=@result[1];//pointe sur le premier élément
        d :=d0;
        s:=@source[1];//pointe sur le premier élément
        sf:=@source[ls];
        inc(sf);
        while s<>sf do begin// sur un entier
            if s^<>ceci then begin//contenu pointer par s <> ceci alors
                d^:=s^;//transfert l’élément
                inc(d);//pointe sur le prochain élément
            end;
            inc(s); // incrémenter s (comme tu voulais le faire dans le for)
        end;
        setlength(result,NativeInt(d)-NativeInt(d0){j});//redimensionne à la bonne dimension
        //result:=ls-ld;
    end;
     
    function Efface(var Source:ansistring; const ceci:ansichar):integer;
    var s,d,d0:^ansichar;
        i,ls,ld:integer;
    begin
        ls:=length(Source);
        d0:=@source[1];//pointe sur le premier élément
        d :=d0;
        s :=d0;
        for i := 0 to ls-1 do begin// for sur un entier
            if s^<>ceci then begin//contenu pointer par s <> ceci alors
                d^:=s^;//transfert l’élément
                inc(d);//pointe sur le prochain élément
            end;
            inc(s); // incrémenter s (comme tu voulais le faire dans le for)
        end;
        ld:=NativeInt(d)-NativeInt(d0);
        setlength(Source,ld);//redimensionne à la bonne dimension
        result:=ls-ld;
    end;
     
    function Efface1(var Source:ansistring; const ceci:ansichar):integer;
    var s,sf,d,d0:^ansichar;
        i,ls,ld:integer;
    begin
        ls:=length(Source);
        d0:=@source[1];//pointe sur le premier élément
        d :=d0;
        s :=d0;
        sf:=@source[ls];
        inc(sf);
        while s<>sf do begin// sur un entier
            if s^<>ceci then begin//contenu pointer par s <> ceci alors
                d^:=s^;//transfert l’élément
                inc(d);//pointe sur le prochain élément
            end;
            inc(s); // incrémenter s (comme tu voulais le faire dans le for)
        end;
        ld:=NativeInt(d)-NativeInt(d0);
        setlength(Source,ld);//redimensionne à la bonne dimension
        result:=ls-ld;
    end;
     
     
    procedure TForm1.Button2Click(Sender: TObject);
    const c='adsflhajsdfljhasdfljhasldkjf';
    var s,t,longuechaine:ansistring;
        ans,vs:ansistring;
        l,x,i,puissance2:integer;
        p:tdate;
    begin
        setlength(longuechaine,1 shl 28);//prépare la chain
        for x:=1 to 1 shl 28 do longuechaine[x]:=ansichar(x and 255);
        puissance2:=5;
     
        memo1.Lines.Add(inttostr(length(longuechaine)));
        memo1.Lines.Add('Procedure   Durée   Longueur');
     
        vs:='';
        s:=longuechaine;
        p:=now;
        for I := 0  to 1 shl puissance2 do begin
           ans:=ansichar(i);
           s:=AnsiStrings.StringReplace(S, ans, vs,[rfReplaceAll]);
        end;
        p:=now-p;
        l:=length(s);
        memo1.Lines.Add('StringReplace  '+ formatdatetime('nnsszzz',p)+' '+inttostr(l));
     
        s:=longuechaine;
        p:=now;
        for I := 0  to 1 shl puissance2 do begin
           x:=efface(s,ansichar(i));
        end;
        p:=now-p;
        l:=length(s);
        memo1.Lines.Add('Efface  '+ formatdatetime('nnsszzz',p)+' '+inttostr(l));
     
     
        s:=longuechaine;
        p:=now;
        for I := 0  to 1 shl puissance2 do begin
           s:=efface0(s,ansichar(i));
        end;
        p:=now-p;
        l:=length(s);
        memo1.Lines.Add('Efface0 '+ formatdatetime('nnsszzz',p)+' '+inttostr(l));
     
        s:=longuechaine;
        p:=now;
        for I := 0  to 1 shl puissance2 do begin
           x:=efface1(s,ansichar(i));
        end;
        l:=length(s);
        p:=now-p;
        memo1.Lines.Add('Efface1 '+ formatdatetime('nnsszzz',p)+' '+inttostr(l));
     
        s:=longuechaine;
        p:=now;
        for I := 0  to 1 shl puissance2 do begin
           s:=efface2(s,ansichar(i));
        end;
        l:=length(s);
        p:=now-p;
        memo1.Lines.Add('Efface2 '+ formatdatetime('nnsszzz',p)+' '+inttostr(l));
     
        t:='';
        s:=longuechaine;
        p:=now;
        for I := 0  to 1 shl puissance2 do begin
            efface3(s,t,ansichar(i));
            s:=t;
        end;
        p:=now-p;
        l:=length(t);
        memo1.Lines.Add('Efface3 '+ formatdatetime('nnsszzz',p)+' '+inttostr(l));
     
     
     
    end;

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    322
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Janvier 2009
    Messages : 322
    Points : 310
    Points
    310
    Par défaut
    Ajout

    Si en premier l'algorithme ne fait que remplacer tout les caractères par un caractère unique. Et ensuite qu'on les efface on obtient un temps de

    Remplace-Efface 00:13:524s 233832448

    Ce qui logique
    1-Marquer tout les caractères à effacer
    2-Effacer les caractères marqués

    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
     
    procedure Remplace1(var Source:ansistring; const ceci,parca:ansichar);
    var s,sf,d,d0:^ansichar;
        i,ls,ld:integer;
    begin
        ls:=length(Source);
        s:=@source[1];//pointe sur le premier élément
        sf:=@source[ls];
        inc(sf);
        while s<>sf do begin// sur un entier
            if s^=ceci then //contenu pointer par s = ceci alors
                s^:=parca;//transfert l’élément
            inc(s); // incrémenter s 
        end;
    end;
     
    procedure TForm1.Button2Click(Sender: TObject);
    ...
        s:=longuechaine;
        p:=now;
        for I := 0  to 1 shl puissance2 do begin
           remplace1(s,ansichar(i),ansichar(0));
        end;
        x:=efface1(s,ansichar(0));
        p:=now-p;
        l:=length(s);
        memo1.Lines.Add('Efface  '+ formatdatetime('nnsszzz',p)+' '+inttostr(l));
    ...

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 755
    Points : 13 349
    Points
    13 349
    Par défaut
    Premièrement, tu ne fais pas 16, mais 17 boucles
    Deuxièmement, pourquoi n'essayes-tu pas des copies par bloque ?

    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
    function EffaceX(const aSource :AnsiString; const aChar :AnsiChar) :AnsiString;
    var
      P       :PAnsiChar;
      PSource :PAnsiChar;
      PDest   :PAnsiChar;
      PEnd    :PAnsiChar;
      Len     :integer;
      Size    :integer;
     
    begin
      SetLength(Result, Length(aSource));
     
      PSource    := PAnsiChar(aSource);
      PEnd       := PSource +Length(aSource);
      P          := PSource;
      PDest      := PAnsiChar(Result);
      Size       := 0;
     
      while P < PEnd do
      begin
        if P^ = aChar then
        begin
          Len := P -PSource;
          CopyMemory(PDest, PSource, Len);
          inc(Size, Len);
          inc(PDest, Len);
          PSource := P +1;
        end;
     
        inc(P);
      end;
     
      if P <> PSource then
      begin
        Len := P -PSource;
        CopyMemory(PDest, PSource, Len);
        inc(Size, Len);
      end;
     
      SetLength(Result, Size);
    end;
    Tu pourrais encore gagner du temps en augmentant la priorité du processus le temps de l'effacement.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SetPriorityClass(GetCurrentProcess, REALTIME_PRIORITY_CLASS);

  11. #11
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    322
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Janvier 2009
    Messages : 322
    Points : 310
    Points
    310
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    Premièrement, tu ne fais pas 16, mais 17 boucles
    (Je suis un peu rouillé )

    Citation Envoyé par Andnotor Voir le message
    Deuxièmement, pourquoi n'essayes-tu pas des copies par bloque ?
    ...
    Merci pour le code je m'y attaquais ce matin

    Résultat
    J'ai du faire passer les boucle de 33 à 128 car trop serré

    Chaine intiale 268435456 caractères
    Procedure_____Durée______Longueur
    EffaceX 00:47:457 133169152 <-Championne ?
    Efface1 00:47:653 133169152

    Merci ta routine va me simplifier la vie, car je n'aurais à maintenir des routines spécifiques.

    De plus, Il doit avoir moyen d'améliorer ta routine en travaillant directement dans la chaine sans allocation de mémoire :

    Résultat:

    Chaine intiale 268435456 caractères
    Procedure_____Durée______Longueur
    Efface1_______00:47:515__134217728
    EffaceX_______00:48:125__134217728
    EffaceXPlus____00:39:985__134217728 <- Grande Championne

    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
    function EffaceXPlus(var aSource :AnsiString; const aChar :AnsiChar) :integer;
    var
      P       :PAnsiChar;
      PSource :PAnsiChar;
      PDest   :PAnsiChar;
      PEnd    :PAnsiChar;
      Len     :integer;
      Size    :integer;
      La      :integer;
     
    begin
    //  SetLength(Result, Length(aSource));
     
      La         := Length(aSource);
      PSource    := PAnsiChar(aSource);
      PEnd       := PSource +La;
      P          := PSource;
      PDest      := Psource;//PAnsiChar(Result);
      Size       := 0;
     
      while P < PEnd do begin
        if P^ = aChar then begin
          Len := P -PSource;
          CopyMemory(PDest, PSource, Len);
          inc(Size, Len);
          inc(PDest, Len);
          PSource := P +1;
        end;
        inc(P);
      end;
     
      if P <> PSource then
      begin
        Len := P -PSource;
        CopyMemory(PDest, PSource, Len);
        inc(Size, Len);
      end;
     
      SetLength(aSource, Size);
      Result:=La-size;
    end;


    Citation Envoyé par Andnotor Voir le message
    Tu pourrais encore gagner du temps en augmentant la priorité du processus le temps de l'effacement.
    Bonne idée, mais il y a des applications qui ne doivent pas s'arrêter. Optimiser le jus tout en restant collaboratif

    Est-ce que tu as sous la main routine remplaçant une chaine par une autre en utilisant des copies par bloc?

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

Discussions similaires

  1. Petite précision sur les pointeurs
    Par Fonzy007 dans le forum C
    Réponses: 2
    Dernier message: 07/12/2006, 11h25
  2. Précisions sur les recordset DAO
    Par Igricheff dans le forum VBA Access
    Réponses: 2
    Dernier message: 18/01/2005, 17h16
  3. questions sur les pointeurs
    Par Hyoga dans le forum C++
    Réponses: 17
    Dernier message: 08/01/2005, 23h25
  4. Précision sur les sauvegarde à chaud
    Par alxkid dans le forum Administration
    Réponses: 2
    Dernier message: 09/08/2004, 18h55
  5. Pb de débutant sur les pointeurs!!!
    Par benji17c dans le forum C
    Réponses: 6
    Dernier message: 30/09/2003, 17h50

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