R.Tanaka.Ichiro's Blog

主にC# な話題です

目次

Blog 利用状況

ニュース

文字列の連結

今、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());


便利ですね。

投稿日時 : 2007年1月8日 10:28

Feedback

# re: 文字列の連結 2007/01/08 10:31 R・田中一郎

ところで今日も仕事です。あぁ忙しい忙しい。

ちなみに、インターフェイスのコメントのタイムスタンプと、この投稿のタイムスタンプの差で、この投稿内容に費やした時間がバレバレになるなぁ、と今気づいたり^^;

# re: 文字列の連結 2007/01/09 11:17 ぽぴ王子

パクッ

じゃなかった、面白かったのでコメント書きに来ました。
.NETやJavaなんかだと、string型の連結が目に見えて遅かったりするので、当然のことながらStringBuilder(.NET)なりStringBuffer(Java)なりを使うのが当然だと思いますが、VB6の場合ってこのクラスを使うことで速さが極端に変わったりするんでしょうか?
実装としてはなかなか面白いニャーと見てましたが、僕がVB6を使ってた頃はこんなこと全然しなかったので(文字列の連結に時間がかかるイメージがなかったのもある)。

っていうか自分で調べてみろよって話ですね。あとでやってみます。
(でもノートパソコンにしかVS6環境が入っていないのでめんどくさい)

ところで、ダブルクォーテーションは&quot;に変換したほうがいいのでは?とかソースを見ながら思った王子ですが、いかがでしょうか。

# re: 文字列の連結 2007/01/09 15:38 R・田中一郎

>が、VB6の場合ってこのクラスを使うことで速さが極端に変わったりするんでしょうか?

先のサンプルなら、大きく違いが出るのではないかと・・・

>っていうか自分で調べてみろよって話ですね。あとでやってみます。

今、VS2005 の SP1 あてている最中で、遅くて確認できないので宜しくですw

>ところで、ダブルクォーテーションは&quot;に変換したほうがいいのでは?とかソースを見ながら思った王子ですが、いかがでしょうか。

あれ?
これって.Textが変換してくれるものだと勝手に思ってました^^;

# re: 文字列の連結 2007/01/09 19:57 まどか

>VB6の場合ってこのクラスを使うことで速さが極端に変わったりするんでしょうか?

ファイルを読んでテキストボックスに順次追記するような場合がメジャーな例でしょうか。
Midを使うことは昔から技術情報や情報発信があったと思います。

現在、MSDNトップページに出てたりする。
http://support.microsoft.com/kb/306821/ja

# re: 文字列の連結 2007/01/10 0:14 ぽぴ王子

検証してみました。
# んー、リモートデスクトップって便利だなぁ。

田中さんのサンプルで25000回ずつやってみたところ、連結クラス使用で0.3秒、&で連結して36秒という結果になりました。ぜんぜん違いますね。
つーか、試してみて速かったから採用してるんだと思ったのだけど、この目で見てみたかったので改めて自分でもやってみました。

よく考えたら、同じ文字列を連結するのってやったことなかったような気もします。
あったとしてもStringBuilderみたいに比較対象になるモノがなかったので、連結することでまたコピーしなおすなんて思ってもみなかったのかも。

なんにせよ、勉強になりました。ありがとうございます。

# re: 文字列の連結 2007/01/10 11:38 R・田中一郎

まどか さん

>Midを使うことは昔から技術情報や情報発信があったと思います。

僕もどこかで見て、楽しそうなので作って見たのがきっかけでした。
FlexGrid コントロールにのセルにデータを配置する場合、Clip プロパティを使うと爆速になるので、最初に、このクラスを使ってまとめて文字列として連結して、Clip プロパティに渡してました。

・・・あ、これは後でネタにしよう。

----------------------------------
ぽぴ王子 さん

>検証してみました。

ありがとうございました。
僕も無事、SP1 のインストールが完了しました。
・・・でも、バージョン情報を眺めてもSP1の文字が発見できないのは何故?^^;

# re: 文字列の連結 2007/01/26 16:28 やすけ

こういうの探していたんです。

ありがとうございまーす。

# re: 文字列の連結 2007/01/29 12:59 R・田中一郎

どういたしましてー。

# 文字列置換 2008/01/11 11:04 R.Tanaka.Ichiro's Blog

文字列置換

# 文字列置換 2008/01/11 11:05 R.Tanaka.Ichiro's Blog

文字列置換

# vXcOJDXrLNWfVS 2012/01/04 6:25 http://www.kosherbeefjerky.net/

YiE5lj Yet, much is unclear. Could you describe in more details!...

# fMiBHnhQKNWoXcUp 2013/03/22 22:39 http://crork.com/

uAQpwy Looking forward to reading more. Great post.Much thanks again.

# tGFkKZdqvoWXjcMbFFC 2018/12/17 7:21 https://www.suba.me/

FMtXx8 This is a great tip especially to those new to the blogosphere. Short but very accurate info Appreciate your sharing this one. A must read article!

# BQDQawrDlRdyxHIyP 2018/12/19 22:15 https://www.suba.me/

pauors This unique blog is really educating and also diverting. I have chosen many handy advices out of this amazing blog. I ad love to go back again and again. Cheers!

タイトル  
名前  
Url
コメント