VB6 未初期化の配列か判断する方法

解決


サンポート  2008-04-21 19:55:58  No: 100596  IP: 192.*.*.*

VB6で未初期化の配列かどうかを判断する方法はないでしょうか?

○.netだと例外が出る様ですが、VB6には無さそうなので。
○UBOUNDは未初期化の配列だとエラー9になってしまいます。
○関数の頭でOn  Error  Gotoでエラー処理に飛ばすと
  とりあえずエラーにはならないみたいですが・・・。

編集 削除
魔界の仮面弁士  2008-04-21 23:22:49  No: 100597  IP: 192.*.*.*

案1) エラートラップして判断する。
案2) あらかじめ、長さゼロの初期化済み配列を入れておく。
案3) API で判定。

編集 削除
YK  2008-04-22 07:15:09  No: 100598  IP: 192.*.*.*

こんにちは。
一次元目だけでしたら
こんな感じで

Dim arg()   As Long

If Sgn(arg) > 0 Then
    MsgBox "配列あり"
Else
    MsgBox "無し"
End If

ReDim arg(0, 0)
If Sgn(arg) > 0 Then
    MsgBox "配列あり " & UBound(arg)
Else
    MsgBox "無し"
End If

編集 削除
とおりすがり  2008-04-22 11:22:04  No: 100599  IP: 192.*.*.*

こんな感じで・・・。
Redim Preserveの時などには配列の初期化、未初期化にかかわらず、

ReDim Preserve arg(cmnUBoundEx(arg) + 1)
とかで出来るはず・・・。
魔界の仮面弁士さんの言うところの案1です

Public Function cmnUBound(strAry() As Long) As Long
    On Error GoTo cmnUBound_ERR
    
    cmnUBound = UBound(strAry)
    Exit Function

cmnUBound_ERR:
    If Err.Number = 9 Then
        cmnUBound = -1
    End If
End Function

編集 削除
サンポート  2008-04-22 11:42:55  No: 100600  IP: 192.*.*.*

お二人ともありがとうございました。
特にYKさんの方法はまさに悩んでいた配列が
ingteger型の1次元配列ですのでそのまま使えます。

sgnのヘルプを見ると符号をバリアント型の値で返す
数値演算と説明がありましたが、未初期化の変数は
0になるということでしょうか?

試しに
Dim array1() aas integer
Dim intA as integer
intA=Sgn(array1)

MsgBox "Sgn(array1)=" & intA

とすると"Sgn(array1)=0"と表示されましたので
(直接MsgBoxにSgn(array1)を渡すとVBがアプリケーションエラー
  で落ちてしまいました。)

編集 削除
サンポート  2008-04-22 11:50:34  No: 100601  IP: 192.*.*.*

とおりすがりさんありがとうございます。

たぶんご提示いただいた方法が一般的な方法な
気が致します。

よく関数の最後にエラー処理を記述しているのを
見かけるものですから。
エラー発生しても関数のその後の処理を続行する様な
ことはあまりないと思いますので。。。

編集 削除
K.J.K.  2008-04-22 18:28:29  No: 100602  IP: 192.*.*.*

初期化されてない/Eraseされた直後であるかどうかの判定そのものは、

Private Declare Sub CopyMemoryFromSafeArray _
    Lib "kernel32.dll" Alias "RtlMoveMemory" _
(ByRef RetPointer As Long, ByRef Src() As Any, _
 Optional ByVal Length As Long = 4&)

Function IsEmptyIntegerArray(ByRef ArrayOfInteger() As Integer) As Boolean
    Dim pSafeArray As Long
    Call CopyMemoryFromSafeArray(pSafeArray, ArrayOfInteger)
    IsEmptyIntegerArray = CBool(0& = pSafeArray)
End Function

で、可能です。但し、こういうコードを書く手間をかけずに、あらかじめ
配列の状態の管理(UBoundの値の監視など)をしておくほうが楽ですし、
管理もしやすいでしょう。

編集 削除
サンポート  2008-04-23 17:27:36  No: 100603  IP: 192.*.*.*

K.J.Kさんありがとうございます。

>但し、こういうコードを書く手間をかけずに、あらかじめ
>配列の状態の管理(UBoundの値の監視など)をしておくほうが楽ですし、
>管理もしやすいでしょう。

おっしゃるとおりです。
本来はそうあるべきだと思います。

実は他の人の書いたプログラムのメンテナンスをしていて、
関数も長い関数で、でもリスクを考えるといまさら構造から修正するのは
危険だし。。。という事情がありました。

いろんな方にご意見を聞けて大変参考になりました。
とりあえず本件は解決済みにしておきます。

編集 削除