● VBで線形リスト ●

VBはC言語と違って基本的にポインタがない。それでも、線形リストを作りたい。はて、どうしたもんだろ?

C言語は次のような構造体宣言ができる。

    typedef struct _udtList
     char name[20];  /* 名前 */
     char tel[10];   /* 電話番号 */
     struct _udtList *next;/* 次の構造体へのポインタ */
    } udtList; 

VBで構造体を使ってこれと同じことをしようとしても基本的にはできないんだよね。基本的にというのは、やろうと思えばできるからこのように言ったんだけど……。う〜む、まぁ、一言いっておくと、VarPtr という関数を使えばできそうな気がする………。さて、話を元に戻して、正当な、VB的な方法といえば、やっぱりクラスの使用でしょう。クラスはオブジェクトであり、いくらでも生成できる。また、オブジェクトは引数として渡せる。上の構造体と同じことをするには、つまり、クラスを構造体のように扱ってやればいいのである。イメージ的には、次のような構造体を用意すればいいわけである。

    Type udtList
      name As String
      tel As String
      next As Object
    End Type udtList

さぁ〜て、それでは、"clsList"というオブジェクト名のクラスを用意して次のコードを書いちゃいませう。

    Public l_Name As String '名前
    Public l_Tel As String  '電話番号
    Public l_ptr As clsList

どう?これで。"clsList"という名前で、"l_name", "l_Tel", "l_ptr" とメンバがある構造体に見立てることができたでしょ。いと、すばらし。

ここまでいったら、一気に行くよ。フォームモジュールにテキストボックス2つ、コマンドボタン2つ配置して次のコードを書きましょう!!

Private Root As New clsList 'ルートクラス
Private Work As New clsList 'テキストボックス文字列格納用

Private Sub cmdAdd_Click()

  Ifhen Exit Sub
  IfThen Exit Sub

  With Work
    .l_Name = txtName
    .l_Tel = txtTel
  End With

  '線形リストにデータを追加する
  Call AddData(Root, Work)

  txtName = ""
  txtTel = ""

End Sub

Private Sub cmdPrint_Click()

  '線形リストのデータを表示する
  Call PrintData(Root)

End Sub

Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)

  '線形リストで使用したclsListを解放する
  Call ReleaseClass(Root)

  Set Work = Nothing

End Sub

'-------------------------------------------------------------------
' 関数名 : CreateObjClass
' 機能 : clsListオブジェクトを生成する
' 引数 : なし
' 返り値 : clsListオブジェクト
'-------------------------------------------------------------------
Private Function CreateObjClass() As clsList

  Dim nClass As New clsList

  Set CreateObjClass = nClass

End Function

'-------------------------------------------------------------------
' 関数名 : AddData
' 機能 : 線形リストにデータを追加する
' 引数 : (in)srcRoot … ルートクラス
' (in)srcWork … データ格納クラス
' 返り値 : なし
'-------------------------------------------------------------------
Private Sub AddData(ByVal srcRoot As clsList, ByVal srcWork As clsList)

  If srcRoot.l_Name = "" Then

    With srcRoot
      .l_Name = srcWork.l_Name
      .l_Tel = srcWork.l_Tel
      Set .l_ptr = CreateObjClass()
    End With
  Else
    Call AddData(srcRoot.l_ptr, srcWork)
  End If

End Sub

'-------------------------------------------------------------------
' 関数名 : PrintData
' 機能 : 線形リストにデータを表示する
' 引数 : (in)srcRoot … ルートクラス
' 返り値 : なし
'-------------------------------------------------------------------
Private Sub PrintData(ByVal srcRoot As clsList)

  If srcRoot.l_Name <> "" Then
    With srcRoot
      Debug.Print .l_Name
      Debug.Print .l_Tel
      Debug.Print " "
    End With

    Call PrintData(srcRoot.l_ptr)
  End If

End Sub

'-------------------------------------------------------------------
' 関数名 : ReleaseClass
' 機能 : 線形リストで使用したclsListを解放する
' 引数 : (in)srcRoot … ルートクラス
' 返り値 : clsListオブジェクト
'-------------------------------------------------------------------
Private Sub ReleaseClass(ByVal srcRoot As clsList)

  If srcRoot.l_Name <> "" Then
    Call ReleaseClass(srcRoot.l_ptr)
    Set srcRoot = Nothing
  End If

End Sub

おそらく、2分木もこの方法でできるのではないかと思ってしまう今日このごろであった。


戻る