構造体配列の存在チェック

解決


Coffee  2007-07-30 20:36:17  No: 137037

こんにちは。vc掲示板でお世話になったCoffeeと申します。
今度はvbで質問があり投稿しました。

以下のような構造体配列を作成しています。

------------------------------------
public type typAAA
  aaa as integer
  bbb as long
  ccc as string
end type

public XXX() as  typAAA
------------------------------------

使用するときはReDimで再生成をするのですが
ReDimする前にXXXが生成されているか?をチェックしたいのです。

if XXX is nothing then 〜〜〜
if XXX is null then 〜〜〜
if IsNothing(XXX) then 〜〜〜
if IsNull(XXX) then 〜〜〜

でも全てコンパイルエラーでした。
チェックする方法は無いのでしょうか?


KG  2007-07-30 21:00:34  No: 137038

生成されているかというのは、配列の要素があるかどうかということでしょうか。
それとも変数として宣言されているかどうかということでしょうか。


Blue  2007-07-30 22:02:09  No: 137039

参考になりますか?
http://hpcgi1.nifty.com/kenzo30/b_cbbs/cbbs.cgi?mode=al2&namber=37781&rev=&no=0&P=R&KLOG=250


Coffee  2007-07-30 22:30:13  No: 137040

チェックしたいのは  【配列の要素があるかどうか?】 です。

BlueさんのURLからIsArray関数を利用してチェックしてみましたが

エラー
「パブリック オブジェクト モジュールで定義されたユーザー定義型に限り、変数に割り当てることができ、実行時バインディングの関数に渡すことができます。」
と出ました。
これは確かFriend関数がどうとかだったような気がするのですが、よく分かりません/(-_-)\


Blue  2007-07-30 22:42:59  No: 137041

IsArrayはVariant型に対して使うものです。(とリンク先にも書いてあるはず)

On Error GoTo でUBoundの例外を捕まえるのが一番手っ取り早いと思いますよ。
# GetMem4の方法はユーザ定義型で出来るのか自信がないので。


Coffee  2007-07-30 22:49:03  No: 137042

何度も訂正恐縮です。
【配列の要素数を求める】にはUBound関数で求められますが
XXXをRedimしていないとUBound関数は使えません。

ややこしくなったのでまとめると、

XXXを定義した状態(Redimも何もしない。定義しただけの状態)で
XXXはRedimされているか?

を判定したいのです。

ふと思いついた案で
【ZEROは値が無い状態】として

--------------------------------------
Redim XXX(0)

if Ubound(XXX) = 0 then
    '何も値が無いので処理できない
end if
--------------------------------------

とすれば良いのかなぁと…。


KG  2007-07-30 23:18:59  No: 137043

それでも良いかと思います。

要素数が0は初期値で
要素数が1以上なら再定義されている

という判断ですよね?

まぁBlueさんの仰るとおり、UboundのエラーをCatchして処理する方法
も考えられる一つの方法だと思います。


Coffee  2007-07-31 00:56:44  No: 137044

その通りです。
要素数がZEROが初期値と考え、1から有効値と考えます。

Blueさんの案でも良いのですが
なるべくエラーは出さないコーディング規約なので
上記の案でいってみようと思います。自己解決してしまいました。('A`)

お二方共ありがとうございました。


Blue  2007-07-31 02:20:33  No: 137045

># GetMem4の方法はユーザ定義型で出来るのか自信がないので。
試してみたけど(Excel VBAですが)、普通に使えるようです。

Option Explicit

Private Declare Sub GetMem4 Lib "msvbvm60" (ByRef Addr() As Any, RetVal As Long)

Public Type typAAA
    aaa As Integer
    bbb As Long
    ccc As String
End Type

Public XXX() As typAAA

Sub Macro1()
    Dim p As Long
    
    GetMem4 XXX, p

    If p = 0 Then
         MsgBox "ReDimされていない"
    Else
         MsgBox "ReDimされている"
    End If

    ReDim a(0)

    GetMem4 a, p
    
    If p = 0 Then
         MsgBox "ReDimされていない"
    Else
         MsgBox "ReDimされている"
    End If
End Sub

SAFEARRAY Data Type  
http://msdn2.microsoft.com/en-us/library/ms221482.aspx
より先頭4バイトを見れば配列として扱っているかが判定できるというわけなんでしょう。


K.J.K.  2007-07-31 04:25:24  No: 137046

VB(6以前やそれと互換性のあるVBAなど)の配列は、C的な表記では
○ SAFEARRAY*
であって、
× SAFEARRAY
ではありません。言い換えれば、
○ if (NULL == (SAFEARRAY*)psa)
をチェックするのであって、
× if (0 == (SAFEARRAY*)psa->cDims)
をチェックしているわけではありません。


Blue  2007-07-31 09:16:01  No: 137047

>K.J.K.さん

間違って認識していたようです。
メモリの中身を見ているかとばかり思っていました。
VarPtr見たいなものだったんですね。
# 確かにcDimsの値ではないですね。
# ってか、リンク先でSafeArrayGetDimをその後使っているし。 orz


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加