今、VB6 のソフトの機能追加を行っている最中です。
そんな中、文字列の連結を高速化している自作クラスが目にとまったので、懐かしさついでに中身を公開してみます。
'********************************************************
' Strcat Class
' Memo: 高速文字連結クラス(短い文字を何度も連結する時に効果的)
'********************************************************
Private Const mDefBufSize = 65536 'デフォルトのサイズ
Private mText As String '文字列を格納
Private mTextLength As Long '現在の文字長
Private mBufSize As Long '同時に確保する文字数
Private Sub Class_Initialize()
mTextLength = 0
mText = ""
mBufSize = mDefBufSize
End Sub
'********************************************************
' Text Property
'********************************************************
Public Property Get Text() As String
Text = Left$(mText, mTextLength)
End Property
Public Property Let Text(ByRef NewText As String)
mText = NewText
mTextLength = Len(mText)
End Property
'********************************************************
' BufSize Property
'********************************************************
Public Property Let BufSize(ByVal NewBufSize As Long)
If (NewBufSize > 0) Then
mBufSize = NewBufSize
End If
End Property
'********************************************************
' Append Method
'********************************************************
Public Sub Append(AppendString As String)
Dim L As Long: L = Len(AppendString)
If (L = 0) Then
Exit Sub
End If
If (Len(mText) < mTextLength + L) Then
mText = mText & String$(mBufSize, 0)
End If
Mid$(mText, mTextLength + 1, L) = AppendString
mTextLength = mTextLength + L
End Sub
使い方は以下の通りです。
Dim T As New Strcat
Dim i As Long
For i = 0 To 1000000
Call T.Append("A")
Next
Debug.Print T.Text
End
どうして単純に以下のように書かないのか?
Dim T As String
Dim i As Long
For i = 0 To 1000000
T = T & "A"
Next
Debug.Print T.Text
End
理由は簡単で、遅いからです。では何故遅いのでしょうか?
答えは「T = T & "A"」の処理で「変数 T 用の常に新しいメモリ空間に、既存の内容をコピーしているから」です。
つまり、上記を実行すると「T = T & "A"」の度に、以下の手順が繰り返されます。
(1)新しい T のエリアに今までの T の内容を全てコピー。
(2)その後に、"A" を付け加える。
そこで、最初に大きなメモリを確保して、有効な文字列の大きさの次の値を置き換えることで追加するようにしたのが、最初のクラスです。
以下のような処理になります。
最初:"---------------------------"
一回目"A--------------------------" 先頭の1文字を置き換える。
二回目"AA-------------------------" 末尾の1文字を置き換える。
二回目"AAA------------------------" 末尾の1文字を置き換える。
つまり、別の場所に A をコピーする手間がなくなるので、高速に処理できるということになります。
ところで、僕の大好きな .NetFramework2.0 では、同様に文字列の連結を高速にしてくれる次のようなクラス「StringBuilder」が最初から用意されています。
上記の例を置き換えると、次のようになります。
StringBuilder s = new StringBuilder();
for (int i = 0; i <= 1000000; ++i) {
s.Append("A");
}
System.Diagnostics.Debug.WriteLine(s.ToString());
便利ですね。