Concaténer beaucoup de String

Le
Jean-Nicolas BERGER
Bonjour,
J'ai un souci de performances lié au fonctionnement interne de la "somme" de
chaines de caractères sous VB6 (allocation d'espace cible puis recopie de la
chaine 1 puis de la chaine 2), tandis que certains langages (VB.NET par
exemple) proposent une méthode .Append capable de réserver un espace mémoire
à la suite de la chaine 1, pour n'avoir qu'à recopier la chaine 2.
Dans mon cas, j'ai un tableau contenant beaucoup (quelques milliers) de
"petites" String (entre 10 et 50 octets), que j'ai besoin de concaténer dans
une seule chaine résultante. Or je me suis aperçu que les temps de réponses
augmentent de manière exponentielle avec le nombre de petites chaines.
Pour l'instant, pour première optimisation, j'ai juste implémenté un
comptage du nombre de lignes du tableau, pour couper en 4 morceaux, faire
des chaines plus petites, et au final faire chaine1+chaine2+chaine3+chaine4.
Et ça va déjà près de deux fois plus vite qu'en faisant une seule boucle
FOR.
Je pense toutefois qu'il doit exister un système beaucoup plus efficace,
s'appuyant par exemple sur une notion de dichotomie, qui permettrait
d'optimiser réellement la chose.
Quelqu'un aurait-il sous la main un code qui pourrait satisfaire mon besoin?
Merci d'avance pour votre aide.
JN BERGER
Questions / Réponses high-tech
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses Page 1 / 2
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
LE TROLL
Le #15351451
Bonjour,

Ben souvent c'est la boucle qui est utilisée,
avec ses variantes.

for i = 1 to fin
chaine1=chaine1 + chaineX
next i

Tu peu essayer avec un Do While, un goto, ou un
fichier...

--
Romans, logiciels, email, site personnel
http://irolog.free.fr/joe.htm
------------------------------------------------------------------------------------
"Jean-Nicolas BERGER"
dans le message de news:
e%
| Bonjour,
| J'ai un souci de performances lié au
fonctionnement interne de la "somme" de
| chaines de caractères sous VB6 (allocation
d'espace cible puis recopie de la
| chaine 1 puis de la chaine 2), tandis que
certains langages (VB.NET par
| exemple) proposent une méthode .Append capable
de réserver un espace mémoire
| à la suite de la chaine 1, pour n'avoir qu'à
recopier la chaine 2.
| Dans mon cas, j'ai un tableau contenant beaucoup
(quelques milliers) de
| "petites" String (entre 10 et 50 octets), que
j'ai besoin de concaténer dans
| une seule chaine résultante. Or je me suis
aperçu que les temps de réponses
| augmentent de manière exponentielle avec le
nombre de petites chaines.
| Pour l'instant, pour première optimisation, j'ai
juste implémenté un
| comptage du nombre de lignes du tableau, pour
couper en 4 morceaux, faire
| des chaines plus petites, et au final faire
chaine1+chaine2+chaine3+chaine4.
| Et ça va déjà près de deux fois plus vite qu'en
faisant une seule boucle
| FOR.
| Je pense toutefois qu'il doit exister un système
beaucoup plus efficace,
| s'appuyant par exemple sur une notion de
dichotomie, qui permettrait
| d'optimiser réellement la chose.
| Quelqu'un aurait-il sous la main un code qui
pourrait satisfaire mon besoin?
| Merci d'avance pour votre aide.
| JN BERGER
|
|
Jean-marc
Le #15351431
Jean-Nicolas BERGER wrote:
Bonjour,
J'ai un souci de performances lié au fonctionnement interne de la
"somme" de chaines de caractères sous VB6 (allocation d'espace cible
puis recopie de la chaine 1 puis de la chaine 2), tandis que certains
langages (VB.NET par exemple) proposent une méthode .Append capable
de réserver un espace mémoire à la suite de la chaine 1, pour n'avoir
qu'à recopier la chaine 2. Dans mon cas, j'ai un tableau contenant
beaucoup (quelques milliers)
de "petites" String (entre 10 et 50 octets), que j'ai besoin de
concaténer dans une seule chaine résultante. Or je me suis aperçu que
les temps de réponses augmentent de manière exponentielle avec le
nombre de petites chaines. Pour l'instant, pour première optimisation,
j'ai juste implémenté un
comptage du nombre de lignes du tableau, pour couper en 4 morceaux,
faire des chaines plus petites, et au final faire
chaine1+chaine2+chaine3+chaine4. Et ça va déjà près de deux fois plus
vite qu'en faisant une seule boucle FOR.
Je pense toutefois qu'il doit exister un système beaucoup plus
efficace, s'appuyant par exemple sur une notion de dichotomie, qui
permettrait d'optimiser réellement la chose.
Quelqu'un aurait-il sous la main un code qui pourrait satisfaire mon
besoin? Merci d'avance pour votre aide.
JN BERGER



Bonjour,

Et oui, il est connu que la concaténation via "&" est horriblement lente.

Pour pallier à ça, on utilise une méthode toute simple qui consiste à
préallouer de la place et à concaténer par remplacement avec Mid$().

Les performances sont plusieurs milliers de fois meilleures, sinon plus,
en fonction de la taille de ce que tu concatènes.



Voila un petit module qui fait cela, je te laisse le transformer en classe,
je n'ai pas eu le temps de le faire:

'---------------------------------------------------------------------------------------
' Module : Concat.bas
' DateTime : 24/02/2006 20:30
' Author : Jean-Marc
' Purpose : Fast concatenation functions
'---------------------------------------------------------------------------------------

Option Explicit

Private Const BUFFER_CHUNK_SIZE As Long = 15000 ' for concat
Private sBuffer As String ' Static buffer for
strings concatenation
Private lOffset As Long ' Technical offest for
next insertion
'

'-------------------
' PUBLIC FUNCTIONS -
'-------------------
' Public Sub ReInit()
' Public Sub SetString(ByRef Source As String)
' Public Function GetString() As String
' Public Sub Concat(ByRef NewString As String)

'-----------------
' IMPLEMENTATION -
'-----------------

'---------------------------------------------------------------------------------------
' Procedure : ReInit
' DateTime : 15/12/2005 20:46
' Author : Jean-Marc
' Purpose : Simple Reinitialisation for Concat;
' This function must be called before starting to concatenate
'---------------------------------------------------------------------------------------
'
Public Sub ReInit()
Dim bErrRet As Boolean

On Error GoTo ReInit_Error

sBuffer = vbNullString
lOffset = 0

On Error GoTo 0
Exit Sub

ReInit_Error:
'szErrTxt = "Error " & Err.Number & " (" & Err.Description & ") in
procedure ReInit_Error() of module Concat.bas"
' traiter l'erreur ici
End Sub

'---------------------------------------------------------------------------------------
' Procedure : SetString
' DateTime : 15/12/2005 20:47
' Author : Jean-Marc
' Purpose : Use this to initialize the string with a value
'---------------------------------------------------------------------------------------
'
Public Sub SetString(ByRef Source As String)
Dim szErrTxt As String
Dim bErrRet As Boolean

On Error GoTo SetString_Error

sBuffer = Source & String(BUFFER_CHUNK_SIZE, 0)

On Error GoTo 0
Exit Sub

SetString_Error:
' szErrTxt = "Error " & Err.Number & " (" & Err.Description & ") in
procedure SetString() of module Concat.bas"
' traiter l'erreur ici
End Sub

'---------------------------------------------------------------------------------------
' Procedure : GetString
' DateTime : 15/12/2005 20:48
' Author : Jean-Marc
' Purpose : This function returns the value of the string in the buffer
(concat)
'---------------------------------------------------------------------------------------
'
Public Function GetString() As String
Dim szErrTxt As String
Dim bErrRet As Boolean

On Error GoTo GetString_Error

GetString = left(sBuffer, lOffset)

On Error GoTo 0
Exit Function

GetString_Error:

'szErrTxt = "Error " & Err.Number & " (" & Err.Description & ") in
procedure GetString() of module Concat.bas"
' traiter l'erreur ici
End Function

'---------------------------------------------------------------------------------------
' Procedure : Concat
' DateTime : 15/12/2005 20:48
' Author : Jean-Marc
' Purpose : This function is used to concatenate a new string into the
local static buffer
'---------------------------------------------------------------------------------------
'
Public Sub Concat(ByRef NewString As String)
Dim szErrTxt As String
Dim bErrRet As Boolean
Dim lNewStrLen As Long

On Error GoTo Concat_Error

lNewStrLen = Len(NewString)
' Allocate more space in buffer if needed
If (lOffset + lNewStrLen) >= Len(sBuffer) Then
sBuffer = sBuffer & String$(BUFFER_CHUNK_SIZE, 0)
End If
' just insert new text by replacing the spaces with Mid() function
Mid(sBuffer, lOffset + 1, lNewStrLen) = NewString
lOffset = lOffset + lNewStrLen

On Error GoTo 0
Exit Sub

Concat_Error:
'szErrTxt = "Error " & Err.Number & " (" & Err.Description & ") in
procedure Concat of Feuille Form1"
' traiter l'erreur ici
End Sub


Les perfs sont incroyables, tu verras.

Cordialement;


--
Jean-marc Noury (jean_marc_n2)
Microsoft MVP - Visual Basic
mailto: remove '_no_spam_' ;
FAQ VB: http://faq.vb.free.fr/
François Picalausa
Le #15351421
On Jul 20, 11:15 pm, "Jean-Nicolas BERGER"
internet.fr> wrote:
Bonjour,
J'ai un souci de performances lié au fonctionnement interne de la "somm e" de
chaines de caractères sous VB6 (allocation d'espace cible puis recopie de la
chaine 1 puis de la chaine 2), tandis que certains langages (VB.NET par
exemple) proposent une méthode .Append capable de réserver un espace mémoire
à la suite de la chaine 1, pour n'avoir qu'à recopier la chaine 2.
Dans mon cas, j'ai un tableau contenant beaucoup (quelques milliers) de
"petites" String (entre 10 et 50 octets), que j'ai besoin de concaténer dans
une seule chaine résultante. Or je me suis aperçu que les temps de r éponses
augmentent de manière exponentielle avec le nombre de petites chaines.
Pour l'instant, pour première optimisation, j'ai juste implémenté un
comptage du nombre de lignes du tableau, pour couper en 4 morceaux, faire
des chaines plus petites, et au final faire chaine1+chaine2+chaine3+chain e4.
Et ça va déjà près de deux fois plus vite qu'en faisant une seule boucle
FOR.
Je pense toutefois qu'il doit exister un système beaucoup plus efficace,
s'appuyant par exemple sur une notion de dichotomie, qui permettrait
d'optimiser réellement la chose.
Quelqu'un aurait-il sous la main un code qui pourrait satisfaire mon beso in?



Hello,

Le problème vient comme tu l'as indiqué de la réallocation fréquente
de mémoire.

Il y a au moins deux solutions qui permettent de résoudre le problème:
1/ Préallocation de blocs de mémoires par String$, concaténation par
le mot clé (et non la fonction) Mid
2/ Allocation par bloc d'un tableau de string (avec allocations par
blocs), la chaine finale étant obtenue par préallocation d'une chaine
par String et copie par mid, à l'aide des peu couteuses opérations
LenB (déférencement d'un pointeur) et division finale par 2 (ce que
fait Len, si ce n'est qu'il le fait pour chaque String).

A priori, la deuxième solution demande souvent des petits blocs de
mémoires, sauf pour la concaténation finale, alors que la première
demande peu souvent de plus gros blocs. (une combinaison des deux
méthodes est probablement envisageable.

Néanmoins, comme l'a exprimé LE TROLL, si tu peux réaliser ton output
directement dans un flux, tel un fichier, un socket, ... tu auras un
gain énorme en performances.

Voici une implémentation possible de la première méthode:
'Dans un module de classe
Option Explicit

Private mInternal As String
Private mLenB As Long 'en bytes
Private mBlocSize As Long 'en charactères

Public Property Get BlocSize() As Long
BlocSize = mBlocSize
End Property

Public Property Let BlocSize(Value As Long)
mBlocSize = Value
End Property

Public Sub Alloc(BlocCount As Long)
If (BlocCount > 0) Then
mInternal = mInternal & String$(mBlocSize * BlocCount,
vbNullChar)
ElseIf (BlocCount < 0) Then
mInternal = Left$(mInternal, Len(mInternal) + mBlocSize *
BlocCount)
End If
End Sub

Public Function ToString() As String
ToString = Left$(mInternal, mLenB / 2)
End Function

Public Sub Clear(Optional DeAlloc As Boolean = False)
mLenB = 0

If (DeAlloc) Then
mInternal = String$(mBlocSize, vbNullChar)
End If
End Sub

Public Sub Append(Text As String)
Dim AllocLength As Long

AllocLength = LenB(Text) - (LenB(mInternal) - mLenB)
If (AllocLength > 0) Then
Alloc (AllocLength / mBlocSize + 1)
End If

Mid$(mInternal, mLenB / 2 + 1) = Text
mLenB = mLenB + LenB(Text)
End Sub

Private Sub Class_Initialize()
mLenB = 0
mBlocSize = 1024
mInternal = String$(mBlocSize, vbNullChar)
End Sub

'Un exemple d'utilisation
Dim a As New StringBuilder
Dim i As Long

For i = 0 To 5000
a.Append "Test"
a.Append "Toto"
Next i
Jean-marc
Le #15351411
François Picalausa wrote:
On Jul 20, 11:15 pm, "Jean-Nicolas BERGER"
Hello,

Le problème vient comme tu l'as indiqué de la réallocation fréquente
de mémoire.

Il y a au moins deux solutions qui permettent de résoudre le problème:
1/ Préallocation de blocs de mémoires par String$, concaténation par
le mot clé (et non la fonction) Mid
2/ Allocation par bloc d'un tableau de string (avec allocations par
blocs), la chaine finale étant obtenue par préallocation d'une chaine
par String et copie par mid, à l'aide des peu couteuses opérations
LenB (déférencement d'un pointeur) et division finale par 2 (ce que
fait Len, si ce n'est qu'il le fait pour chaque String).

A priori, la deuxième solution demande souvent des petits blocs de
mémoires, sauf pour la concaténation finale, alors que la première
demande peu souvent de plus gros blocs. (une combinaison des deux
méthodes est probablement envisageable.



Hello :-)

J'ai benchmarké ta classe et mon module, les performances sont
similaires (pas de surprise, puisque c'est la même méthode), et j'ai
comparé avec l'implémentation naïve avec "&".
Résultats:

Pour 100.000 concaténations, on gagne un facteur 500. la méthode par
mid() est donc sur cet exemple 500 fois plus rapide.

70 milliseconde avec Mid$() contre 35 secondes avec le "&".
Les résultats parlent d'eux même ...

Note: Il suffit d'augmenter mBlocSize (que tu as fixé à 1024) pour
augmenter encore de façon très sensible les perfs. Partant du principe
qu'on est pas à 10k près, je pense que 10240 est probablement une
meilleure valeur, pourquoi se priver!

A noter qu'en fonction de la taille des trucs à concaténer, on peut jouer
avec cette valeur pour la faire correspondre pile-poil au cas que l'on
traite.

Le lecteur pourra sans problème "externaliser" le paramètre en ajoutant
une jolie propriété à la classe permettant de "superseder" la valeur
par défaut :-)


--
Jean-marc Noury (jean_marc_n2)
Microsoft MVP - Visual Basic
mailto: remove '_no_spam_' ;
FAQ VB: http://faq.vb.free.fr/
François Picalausa
Le #15351401
On Jul 21, 10:48 am, François Picalausa
On Jul 20, 11:15 pm, "Jean-Nicolas BERGER"

internet.fr> wrote:
> Bonjour,
> J'ai un souci de performances lié au fonctionnement interne de la "so mme" de
> chaines de caractères sous VB6 (allocation d'espace cible puis recopi e de la
> chaine 1 puis de la chaine 2), tandis que certains langages (VB.NET par
> exemple) proposent une méthode .Append capable de réserver un espac e mémoire
> à la suite de la chaine 1, pour n'avoir qu'à recopier la chaine 2.
> Dans mon cas, j'ai un tableau contenant beaucoup (quelques milliers) de
> "petites" String (entre 10 et 50 octets), que j'ai besoin de concatén er dans
> une seule chaine résultante. Or je me suis aperçu que les temps de réponses
> augmentent de manière exponentielle avec le nombre de petites chaines.
> Pour l'instant, pour première optimisation, j'ai juste implémenté un
> comptage du nombre de lignes du tableau, pour couper en 4 morceaux, fai re
> des chaines plus petites, et au final faire chaine1+chaine2+chaine3+cha ine4.
> Et ça va déjà près de deux fois plus vite qu'en faisant une seu le boucle
> FOR.
> Je pense toutefois qu'il doit exister un système beaucoup plus effica ce,
> s'appuyant par exemple sur une notion de dichotomie, qui permettrait
> d'optimiser réellement la chose.
> Quelqu'un aurait-il sous la main un code qui pourrait satisfaire mon be soin?

Hello,

Le problème vient comme tu l'as indiqué de la réallocation fréque nte
de mémoire.

Il y a au moins deux solutions qui permettent de résoudre le problème:
1/ Préallocation de blocs de mémoires par String$, concaténation par
le mot clé (et non la fonction) Mid
2/ Allocation par bloc d'un tableau de string (avec allocations par
blocs), la chaine finale étant obtenue par préallocation d'une chaine
par String et copie par mid, à l'aide des peu couteuses opérations
LenB (déférencement d'un pointeur) et division finale par 2 (ce que
fait Len, si ce n'est qu'il le fait pour chaque String).

A priori, la deuxième solution demande souvent des petits blocs de
mémoires, sauf pour la concaténation finale, alors que la première
demande peu souvent de plus gros blocs. (une combinaison des deux
méthodes est probablement envisageable.

Néanmoins, comme l'a exprimé LE TROLL, si tu peux réaliser ton outp ut
directement dans un flux, tel un fichier, un socket, ... tu auras un
gain énorme en performances.

Voici une implémentation possible de la première méthode:
'Dans un module de classe
Option Explicit

Private mInternal As String
Private mLenB As Long 'en bytes
Private mBlocSize As Long 'en charactères

Public Property Get BlocSize() As Long
BlocSize = mBlocSize
End Property

Public Property Let BlocSize(Value As Long)
mBlocSize = Value
End Property

Public Sub Alloc(BlocCount As Long)
If (BlocCount > 0) Then
mInternal = mInternal & String$(mBlocSize * BlocCount,
vbNullChar)
ElseIf (BlocCount < 0) Then
mInternal = Left$(mInternal, Len(mInternal) + mBlocSize *
BlocCount)
End If
End Sub

Public Function ToString() As String
ToString = Left$(mInternal, mLenB / 2)
End Function

Public Sub Clear(Optional DeAlloc As Boolean = False)
mLenB = 0

If (DeAlloc) Then
mInternal = String$(mBlocSize, vbNullChar)
End If
End Sub

Public Sub Append(Text As String)
Dim AllocLength As Long

AllocLength = LenB(Text) - (LenB(mInternal) - mLenB)
If (AllocLength > 0) Then
Alloc (AllocLength / mBlocSize + 1)
End If

Mid$(mInternal, mLenB / 2 + 1) = Text
mLenB = mLenB + LenB(Text)
End Sub

Private Sub Class_Initialize()
mLenB = 0
mBlocSize = 1024
mInternal = String$(mBlocSize, vbNullChar)
End Sub

'Un exemple d'utilisation
Dim a As New StringBuilder
Dim i As Long

For i = 0 To 5000
a.Append "Test"
a.Append "Toto"
Next i



[Après une erreur de manipulation, je continue]
Et de la seconde méthode:

Option Explicit

Private mStrings() As String
Private mNOL As Long 'Number of elements (strings stored)
Private mBlocSize As Long

Public Property Get BlocSize() As Long
BlocSize = mBlocSize
End Property

Public Property Let BlocSize(Value As Long)
mBlocSize = Value
End Property

Public Function ToString() As String
Dim result As String
Dim resultLenB As Long
Dim resultPos As Long
Dim i As Long

For i = 0 To mNOL - 1
resultLenB = resultLenB + LenB(mStrings(i))
Next i

result = String$(resultLenB / 2, vbNullChar)
resultPos = 1

For i = 0 To mNOL - 1
Mid$(result, resultPos) = mStrings(i)
resultPos = resultPos + Len(mStrings(i))
Next i
End Function

Public Sub Append(Text As String)
If mNOL > UBound(mStrings) Then
Alloc
End If

mStrings(mNOL) = Text
mNOL = mNOL + 1
End Sub

Private Sub Alloc()
ReDim Preserve mStrings(UBound(mStrings) + mBlocSize)
End Sub

Private Sub Class_Initialize()
mBlocSize = 256
ReDim mStrings(mBlocSize)
mNOL = 0
End Sub

Bien entendu, il faudrait bencher correctement le tout pour voir
laquelle des deux est plus rapide (Jean-Marc, si tu
m'entends ;-) )...

Ceci tient compte du fait qu'on ne cherche qu'a concaténer une chaine
de caractère. Si on souhaitais supprimer quelques caractères en in de
chaine, réaliser un "instr", ou un "mid", la première solution
présenterait un net avantage dans la facilité à écrire le code.

François
Jean-marc
Le #15351391
François Picalausa wrote:


Private Sub Alloc()
ReDim Preserve mStrings(UBound(mStrings) + mBlocSize)
End Sub

Private Sub Class_Initialize()
mBlocSize = 256
ReDim mStrings(mBlocSize)
mNOL = 0
End Sub



Re,

Est ce que sémantiquement la variable mBlocSize ne devrait
pas plutot s'appeler mBlocsNumber, voire mNumberBlocs ?

Je vais quoi qu'il en soit bencher tout ça.

<private>Office Ultimate 2007, c'est trèèèèès cool, en particulier
PowerPoint. Migration faite</private>

--
Jean-marc Noury (jean_marc_n2)
Microsoft MVP - Visual Basic
mailto: remove '_no_spam_' ;
FAQ VB: http://faq.vb.free.fr/
Jean-Nicolas BERGER
Le #15351371
Merci beaucoup à François et Jean-Marc pour votre investissement très rapide
et plus que conséquent.
Vos codes vont m'être très précieux.
Bonne journée.
JN.


"Jean-marc" de news: 46a1dbc6$0$14242$
François Picalausa wrote:


Private Sub Alloc()
ReDim Preserve mStrings(UBound(mStrings) + mBlocSize)
End Sub

Private Sub Class_Initialize()
mBlocSize = 256
ReDim mStrings(mBlocSize)
mNOL = 0
End Sub



Re,

Est ce que sémantiquement la variable mBlocSize ne devrait
pas plutot s'appeler mBlocsNumber, voire mNumberBlocs ?

Je vais quoi qu'il en soit bencher tout ça.

<private>Office Ultimate 2007, c'est trèèèèès cool, en particulier
PowerPoint. Migration faite</private>

--
Jean-marc Noury (jean_marc_n2)
Microsoft MVP - Visual Basic
mailto: remove '_no_spam_' ;
FAQ VB: http://faq.vb.free.fr/




François Picalausa
Le #15351361
On Jul 21, 12:11 pm, "Jean-marc"
François Picalausa wrote:
> Private Sub Alloc()
> ReDim Preserve mStrings(UBound(mStrings) + mBlocSize)
> End Sub

> Private Sub Class_Initialize()
> mBlocSize = 256
> ReDim mStrings(mBlocSize)
> mNOL = 0
> End Sub

Re,

Est ce que sémantiquement la variable mBlocSize ne devrait
pas plutot s'appeler mBlocsNumber, voire mNumberBlocs ?

Je vais quoi qu'il en soit bencher tout ça.



Hello,

Quand je te disais que le copier-coller était le meilleur ennemi du
développeur!
Effectivement, sémantiquement, mBlocSize est incorrect!

<private>Office Ultimate 2007, c'est trèèèèès cool, en particul ier
PowerPoint. Migration faite</private>



<private>La conversion a été tellement rapide! /note pour l'avenir
proche: trouver rapidement une nouvelle techno un peu cool/</private>

François
Jean-marc
Le #15351351
François Picalausa wrote:
On Jul 21, 10:48 am, François Picalausa
On Jul 20, 11:15 pm, "Jean-Nicolas BERGER"






Hello !

Bien entendu, il faudrait bencher correctement le tout pour voir
laquelle des deux est plus rapide (Jean-Marc, si tu
m'entends ;-) )...




La seconde méthode est environ 50% plus lente, c'est à dire:
Pour le même nombre d'opérations:
Méthode 1 : 100 ms
Méthode 2 : 150 ms

à comparer avec la méthode naïve : 54000 ms (54 secondes ...)

Vainqueur (sans surprise, pour moi) : Solution 1, Mid()

Ceci tient compte du fait qu'on ne cherche qu'a concaténer une chaine
de caractère. Si on souhaitais supprimer quelques caractères en in de
chaine, réaliser un "instr", ou un "mid", la première solution
présenterait un net avantage dans la facilité à écrire le code.



Ce qui vient encore renforcer tout ça: sans aucun doute, la Solution 1
est la meilleure, en performance, souplesse et même d'un point de
vue esthétique (mais ça, c'est personnel).


--
Jean-marc Noury (jean_marc_n2)
Microsoft MVP - Visual Basic
mailto: remove '_no_spam_' ;
FAQ VB: http://faq.vb.free.fr/
Renfield
Le #15396671
Bonjour,

j'utilises un tableau de chaines, et l'instruction Join pour recoller
le tout :

http://www.vbfrance.com/codes/CONCATENATION-RAPIDE-CHAINES-SANS-API_39831.a spx




Option Explicit

Private mxsValues() As String
Private mnCount As Long
Private mnCapacity As Long

'# Nombre de cases qque l'on ajoute au tableau lorsqu'il est trop
petit
Private Const BLOCKSIZE As Long = 250

'# Méthode qui permet l'ajout d'éléments dans le tampon
Public Sub Append(ByVal szString As String)
If mnCount = mnCapacity Then
'# Le tableau est trop petit...
'# On agrandit sa taille de BLOCKSIZE
ResizeArray
End If

'# On ajoute notre chaine dans le tableau
mxsValues(mnCount) = szString
'# Et on incrémente le compteur
mnCount = mnCount + 1
End Sub

'# Propriété par défault
'# on recolle simplement les morceaux...
Public Property Get Value() As String
Value = Join(mxsValues, vbNullString)
End Property

'# On vide le buffer
Public Sub Clear()
mnCount = 0
mnCapacity = 0
Erase mxsValues
End Sub

Private Sub ResizeArray()
ReDim Preserve mxsValues(mnCapacity + BLOCKSIZE - 1) As String
mnCapacity = mnCapacity + BLOCKSIZE
End Sub



Je vous laisse benchmarker...
Publicité
Poster une réponse
Anonyme