- PR -

昔の VB で要素数 0 の配列を使いたい

投稿者投稿内容
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2005-12-27 00:45
私の場合、割り切って要素数-1までしか使用しないようにしています。
Java/Cのような感じですね。

UBoundの戻り値は配列の要素数と考え、
0から要素数-1までが、確保されている領域と考えるようにしています。

コード:
dim str(10) as string
dim i as integer

for i = 0 to ubound(str) - 1
    '処理
next


コード量も領域も無駄なのですが、
Javaに慣れているので、コーディングしやすいです。
Nullの扱いに対する解決にはなっていませんが。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2005-12-27 09:34
引用:

じゃんぬねっとさんの書き込み (2005-12-26 23:25) より:
一応使用例のコードは提示していますよ。
ただ、見て頂くと察しが付くと思いますが、これも、どの VB でも使えるというわけでは...

ありがとうございます。やっぱり、ちょっと UBound が -1 になるような配列、に未練がありまして、SafeArrayGetDim と GetMem4 の API で検索しているのですが、これらは OLE API の一種になるので、このAPI群の中で要素数0の配列を生成するというのもあるのかな〜、と思って探しています。たとえば、
コード:
Option Explicit

Public Sub Foo(ByRef x As Variant)
    ReDim x(3)
End Sub

Private Sub Command1_Click()
    ReDim a(1) As String
    Call Foo(a)
    Debug.Print "UBound(a) = " & UBound(a)
End Sub


とすると、Foo は配列の要素数を2(UBoundは1)から4(UBoundは3)に変更できます(内部的には配列を変更というより変数を変更することになる?)が、これと同じインターフェースを持った DLL を作って、その中で ReDim x(-1) に相当することを OLE API でできれば、非常に楽になるのですが、こういうことって可能なのでしょうか?

引用:

かつのりさんの書き込み (2005-12-27 00:45) より:
UBoundの戻り値は配列の要素数と考え、
0から要素数-1までが、確保されている領域と考えるようにしています。

なるほど。私はなぜか、「1から要素数までが、確保されている領域」(0を使わない)というのだけを考えていたのですが、ご指摘のように0から始めるやりかたもあるんですね。こっちのほうがJava/Cに近そうですね。ただ、やっぱりインデックスに不正な値を使ってもエラーにならないので、配列アクセスのたびにインデックスをチェックするsetter/getterを使えば確実かな、とも思っています。ただ、見た目が煩雑になってしまうのでちょっと悩んでいます。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2005-12-27 10:09
引用:

unibonさんの書き込み (2005-12-27 09:34) より:

SafeArrayGetDim と GetMem4 の API で検索しているのですが、これらは OLE API の一種になるので、このAPI群の中で要素数0の配列を生成するというのもあるのかな〜、と思って探しています。


うーん、こういうことでしょうか?

コード:

    Option Explicit

    '/ SafeArrayAllocDescriptor 関数
    Private Declare Function SafeArrayAllocDescriptor Lib "OLEAUT32.DLL" ( _
        ByVal cDims     As Long, _
        ByRef ppsaOut() As Any   _
    ) As Long

    '/ テスト用のユーザー定義型
    Private Type UserDefine
        Member1 As Integer
        Member2 As String
    End Type

    '/ テスト用のイベント プロシージャ
    Private Sub Command1_Click()
        ' String[] の場合
        Dim stArray() As String
        Call SafeArrayAllocDescriptor(1, stArray())
        Call MsgBox("LBound = " & CStr(LBound(stArray())) & vbNewLine & "UBound = " & CStr(UBound(stArray())))

        ' Object[] の場合
        Dim oArray() As Object
        Call SafeArrayAllocDescriptor(1, oArray())
        Call MsgBox("LBound = " & CStr(LBound(oArray())) & vbNewLine & "UBound = " & CStr(UBound(oArray())))

        ' 標準コントロール型[] の場合
        Dim pTextBoxes() As TextBox
        Call SafeArrayAllocDescriptor(1, pTextBoxes())
        Call MsgBox("LBound = " & CStr(LBound(pTextBoxes())) & vbNewLine & "UBound = " & CStr(UBound(pTextBoxes())))

        ' ユーザー定義型[] の場合
        Dim uArray() As UserDefine
        Call SafeArrayAllocDescriptor(1, uArray())
        Call MsgBox("LBound = " & CStr(LBound(uArray())) & vbNewLine & "UBound = " & CStr(UBound(uArray())))
    End Sub


ただ、空の配列というのは VB 的には UBound(obj[]) = -1 には変わりはなさそうです。
これは致し方のないように思えますが... やっぱり、ダメっすか? (^^;)

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
踏蹟
会議室デビュー日: 2003/09/12
投稿数: 10
投稿日時: 2005-12-27 10:51
VBじゃなくVBAしか使ったことが無いんですが、動的配列で宣言してReDimする前ならUBoundが-1になるはずです。

Dim a()
よねKEN
ぬし
会議室デビュー日: 2003/08/23
投稿数: 472
投稿日時: 2005-12-27 10:54
■ 変数の配列が設定されたか取得するには?
http://homepage1.nifty.com/MADIA/vb/vb_bbs2/200312_03120105.html
■Orator's IO
http://yaplog.jp/orator/monthly/200312/

他にも各種空の配列の作り方もどこかで魔界の仮面弁士さんが回答されていたような記憶がありますが、忘れました(^^;

#VBで配列ならキーワードはK.J.K.さんか魔界の仮面弁士さんですかねぇ。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2005-12-27 11:10
引用:

踏蹟さんの書き込み (2005-12-27 10:51) より:

VBじゃなくVBAしか使ったことが無いんですが、動的配列で宣言してReDimする前ならUBoundが-1になるはずです。
Dim a()


ならないみたいです。
インデックスは -1 ではなく未定義の状態です。
VB でも VBA でも実行時エラーになることを確認しています。

引用:

よねKENさんの書き込み (2005-12-27 10:54) より:

Orator's IO


VB のことは、弁さんには敵いませんね。
先に書きました「SafeArrayAllocDescriptor」のまさにそれが載ってます。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2005-12-27 11:27
引用:

じゃんぬねっとさんの書き込み (2005-12-27 10:09) より:
うーん、こういうことでしょうか?


これです、これです。ありがとうございます。
SafeArrayAllocDescriptor で検索すればよかったのですね。

引用:

じゃんぬねっとさんの書き込み (2005-12-27 10:09) より:
ただ、空の配列というのは VB 的には UBound(obj[]) = -1 には変わりはなさそうです。
これは致し方のないように思えますが... やっぱり、ダメっすか? (^^


UBound が -1 なのは数え方の違いだけなので構いません(VB の流儀だと割り切ります)。
ただ、気づいたのですが、これを施した配列に対し、さらに ReDim Preserve はできないみたいですね。SafeArrayAllocDescriptor だけでは足りないのか、私が勘違いしているのか分かりませんが。
もっとも Preserve なしの ReDim はできるみたいなので、とても便利です。
この手法でいろいろやってみたいと思います。

引用:

踏蹟さんの書き込み (2005-12-27 10:51) より:
VBじゃなくVBAしか使ったことが無いんですが、動的配列で宣言してReDimする前ならUBoundが-1になるはずです。

Dim a()


これは Excel 97 の VBA ではできませんでした。新しい Excel ではできるのでしょうか。
なお、余談ですが、VBScript だと ReDim a(-1) ができて UBound(a) = -1 になるみたいでした。これは意外でした。昔から出来たのでしょうか。VBScript は昔から使っていたのですが、VB/VBA と同様にできないものだと思っていました。
踏蹟
会議室デビュー日: 2003/09/12
投稿数: 10
投稿日時: 2005-12-27 11:55
すみません、確かにエラーになりますね。
UBoundが-1かどうかの判定をどこかで使った記憶はあるのですが、Spritか何かだったんでしょうかね。

スキルアップ/キャリアアップ(JOB@IT)