構造体のメンバについて


ペンネーム  2004-12-02 06:06:44  No: 87053

構造体のメンバについて質問です。
作成中の構造体は、メンバの数や階層などが深いのですが、
デバック実行を実施した時、アプリケーションエラーで
プログラムが終了してしまいます。
原因は、構造体の作りにあるのでしょうか?
また、上記事象を回避する案などがありましたら教えて下さい。
ちなみにVB5.0で作業を行っています。


たくみ  2004-12-02 11:40:30  No: 87054

制限値は調べてないのでなんなのですが・・

> メンバの数や階層などが深いのですが
とありますが、いったいどのくらいの数なんでしょう?
ここに公開できないような長さ?なのでしょうか?
ちらっとその定義されているコード部分だけでも
貼ってみられたらどうでしょう?

で、その構造体ってそもそも分けれないんですか?
例えば、多少格好悪いけど、
(まず似たような構造体名で2つ3つType作っておいて)
制御する添え字、インデックス値を同じにして
データ読み取り、書き込みするよう組めば、
むりむり分けれるのでは、と。

アプリケーションエラー、それじゃ回避できない??


ペンネーム  2004-12-02 18:59:51  No: 87055

たくみさん返答ありがとうございます。
定義されているコード部分を下記に載せます。

Type Torihikisakijoho
    BytKoumoku(2)     As Byte
    StrKoumoku        As String * 30
End Type

Type TorihikiSeigyojoho
    BytKoumoku(2)     As Byte
    StrKoumoku        As String * 61
End Type

Type HeaderBlock
    BytKoumoku(2)     As Byte
End Type

Type Tanmatujyoutaijoho
    BytKoumoku(27)     As Byte
End Type

Type TransactionSikibetu
    BytKoumoku(19)     As Byte
    StrKoumoku        As String * 5
End Type

Type Tanmatugyoumujoho
    BytKoumoku1(4)     As Byte
    StrKoumoku1        As String * 5
    BytKoumoku2(1)     As Byte
    StrKoumoku2        As String * 4
    BytKoumoku3(1)     As Byte
    StrKoumoku3        As String * 3
    BytKoumoku4(1)     As Byte
    StrKoumoku4        As String * 1
    BytKoumoku5(1)     As Byte
    StrKoumoku5        As String * 11
    BytKoumoku6(1)     As Byte
    StrKoumoku6        As String * 1
End Type

Type LogicalData
    BytKoumoku(14)    As Byte
    StrKoumoku        As String * 8  'マップ名称
End Type

Type IdCard
    BytKoumoku(2)    As Byte
    StrKoumoku       As String * 10
End Type

Type tagDATA0
    Koumoku(7) As Byte
End Type

Type tagDATA1
    Koumoku(7) As Byte
    Data       As String
End Type

Type tagDATA2
    Koumoku(7) As Byte
    Data       As String * 1
End Type

Type tagDATA3
    Koumoku(7) As Byte
    Data       As String * 2
End Type

Type tagDATA4
    Koumoku(7) As Byte
    Data       As String * 3
End Type

Type tagDATA5
    Koumoku(7) As Byte
    Data       As String * 6
End Type

Type tagDATA6
    Koumoku(7) As Byte
    Data       As String * 7
End Type

Type Furikomi1
    FI0020 As tagDATA5
    FI0060 As tagDATA0
    FI0070 As tagDATA1
    FI0080 As tagDATA1
    FI0090 As tagDATA2
    FI0100 As tagDATA1
    FI0110 As tagDATA1
    FI0120 As tagDATA1
    FI0130 As tagDATA0
    FI0140 As tagDATA0
    FI0190 As tagDATA3
    FI0200 As tagDATA0
    FI0220 As tagDATA0
    FI0240 As tagDATA4
    FI0250 As tagDATA2
    FI0270 As tagDATA2
    FI0290 As tagDATA2
    FI0320 As tagDATA3
    FI0330 As tagDATA6
End Type

Type strin04_01Rec
    Koumoku1   As Torihikisakijoho
    Koumoku2   As TorihikiSeigyojoho
    Koumoku3   As HeaderBlock
    Koumoku4   As Tanmatujyoutaijoho
    Koumoku5   As TransactionSikibetu
    Koumoku6   As Tanmatugyoumujoho
    Koumoku7   As LogicalData
    Koumoku8   As Furikomi1
    Koumoku9   As IdCard
End Type
Global strin04_01 As strin04_01Rec

>(まず似たような構造体名で2つ3つType作っておいて)
>制御する添え字、インデックス値を同じにして
>データ読み取り、書き込みするよう組めば、
>むりむり分けれるのでは、と。
  上記構造体の場合どういう形で構造体を分ければよいでしょうか?
  申し訳ありませんが簡単に記述例など教えていただけましたら大変助かります。


ペンネーム  2004-12-02 20:20:00  No: 87056

ちなみに下記typeのFI0250〜FI0330をコメント化すると、
アプリケーションエラーは出ません。

Type Furikomi1
    FI0020 As tagDATA5
    FI0060 As tagDATA0
    FI0070 As tagDATA1
    FI0080 As tagDATA1
    FI0090 As tagDATA2
    FI0100 As tagDATA1
    FI0110 As tagDATA1
    FI0120 As tagDATA1
    FI0130 As tagDATA0
    FI0140 As tagDATA0
    FI0190 As tagDATA3
    FI0200 As tagDATA0
    FI0220 As tagDATA0
    FI0240 As tagDATA4
    FI0250 As tagDATA2    'コメント化
    FI0270 As tagDATA2    'コメント化
    FI0290 As tagDATA2    'コメント化  →  アプリケーションエラー
    FI0320 As tagDATA3    'コメント化      は出ない。
    FI0330 As tagDATA6    'コメント化
End Type


たくみ  2004-12-02 23:05:20  No: 87057

これって、COBOLの焼き直しとかですか?
・・ぜんぜんはずしてても、この際、発想の転換をしてみられては
どうなんでしょう?

でかいプロジェクトだったり、もうほとんどできあがってて今さら、
という段階なのかも知れませんね。
でもやっぱりVBなんだからもう少しMS$さんの役者たちを活用した方が
非常にすっきり、かつ便利で重宝すると思うのです。

例えば最初のType Torihikisakijohoとかですが、
わざわざTypeにしなくてもDBにテーブル作ってそっちに値を保持させ、
任意のフォーム起動時にレコードセットで取得させたり、
それと同じ考え方でINIファイルで管理したりレジストリで管理したり
すればいいんじゃないかと。
ちなみに私はINIもレジストリも日ごろよく使っていますが
それでトラブったことはほとんどないですよ。

あ、そういうことは普通にやってて、で内部の情報の管理(持たせ方)を
ただ構造体を登場させ出し入れしている、ということなのでしょうか?
もちろん普通ならばそれはそれでいいのでしょうが
今回のようにTypeの定義の多さや階層の深さが疑わしく思えるのなら
いっそそれらTypeをなるべく他の役者に変えてみられてはどうか、
という提案です。

でも、結局たらたらPublic変数とかいっぱい作ってそれらに
Type Torihikisakijohoとかの代替情報入れるのなら
わかりにくく、メンテしづらいし、あんまりメリット感じないよー
と言われるかも。
であれば、おすすめはレコードセット作った後に
GetRowsメソッドを実行し、配列に入れてしまいます。

構文:
array = recordset.GetRows( Rows, Start, Fields )
戻り値:
二次元の配列を返します。
詳しくはヘルプ見てみてください。

このサイト読まれている多くの方も意外と、というかぜんぜん
使っていないんじゃないでしょうか。
もちろん、絶対毎回使ったらいい、という性格のものじゃないですが
あとはその配列でスマートに、らくちんコーディングができるので
一度お試しあれ。

いつまでもいつまでも、いっぱいできたレコードセット殺せなくて
ひきずり回す、という必要もなくなるし。

たぶん、ペンネームさんの場合
Global strin04_01 As strin04_01Rec
とかは少なくともGetRowsの恩恵にあずかれるのではないでしょうか。

PS.
あと気になったのが、
Data       As String * 1
Data       As String * 2
とかです。
ものすごく変数がメモリ浪費するのを懸念しての策だと思ったのですが
ここは普通に、
Data       As String
でやられてはどうでしょう?
実はそれでエラーでなくなったりとかありえませんか??
今、時間がなくなってきたのでその根拠までは
調べれないのでなんですが、なーんか関係あったような・・
単に見当違い、かもしれないのではずしてたらすみません。

・・もし知ってらっしゃる方おられましたら補足お願いします。


たくみ  2004-12-02 23:57:11  No: 87058

なんだか、私の言ってる焦点がぼやけて誤解されそうだったので
少し補足します。

Type strin04_01Rec
    Koumoku1   As Torihikisakijoho
    Koumoku2   As TorihikiSeigyojoho


    Koumoku8   As Furikomi1
    Koumoku9   As IdCard
End Type
Global strin04_01 As strin04_01Rec

のようにどんどん「たばねて」いく考えでなくても
ここはいいのではないでしょうか?ということです。
その観点から、情報「群」を「バラ」で持つことを
考え直したらいいのでは?ということです。

で、それで、Type Torihikisakijohoとかを
単体で、なおかつ「配列」で扱ってもいいのでは?
という提案をしたのですが。
逆になぜどうしても「たばねて」おきたいのかが??
それだったらRDB側で管理(これがさっき言ったレコードセットとか
その発展でGetRowsメソッドの話しの部分)をしたら
すっきりするんじゃないでしょうか、と。

なぜ、こういう「たばねる」必要があるのでしょう??
例えば、やっぱりCOBOLで言う多段階に(たいてい2〜3段に)
階層分けされたあの「ファイルレイアウト」とか「デザインシート」
が目に浮かんで来て、それをそのまんま(メンテしやすいよう)
たばねてコーディングしてみました、ということなのでは?

もし、それはずしてなければ「郷に入っては郷に従え」です。
せっかくのVBコーディングなのですから。


ガッ  2004-12-03 02:56:53  No: 87059

ちなみにオレの環境ではフツーにコンパイル通ったが…
[VB:6 WinXP(Home) Memory:512MB CPU:2.53GHz]


ペンネーム  2004-12-03 03:04:18  No: 87060

たくみさん色々ご教受ありがとうございました。
array = recordset.GetRows( Rows, Start, Fields )ですが、
ヘルプをみましたがいまいち使い方が分かりませんでした。
どこかよいサイトなどがありましたら教えていただきたくよろしくお願い致します。


たくみ  2004-12-03 03:32:13  No: 87061

GetRowsの前に普通にレコードセットは作ったのですよね?
今VB5の環境がないのでVB6での話しで書きます。

上の例で言うとarrayのところの変数を例えば
    Dim RsArray As Variant
として宣言しておきます。
でもってあとは普通にレコードセット作ります。

    Dim Rs As ADODB.Recordset

    Set Rs = New ADODB.Recordset     '毎回ここでNew初期化

    'Rs作成
    Rs.Open SQL, gCnSrc, adOpenStatic, adLockReadOnly, adCmdText
    
    If RsSrc.EOF Then Exit Function
    
    RsArray = RsSrc.GetRows()   '既にRsArrayがあろうとなかろうと上書きさせる仕様
    
    'いったんRsArrayに格納したのですみやかにRsをクローズしておく
    RsSrc.Close: Set RsSrc = Nothing


たくみ  2004-12-03 03:33:53  No: 87062

すみません、今誤って途中で書きかけを送信してしまいました。
すぐ訂正したものを送ります。お待ちを。


たくみ  2004-12-03 04:09:40  No: 87063

さきほどの書きかけ誤送信分の訂正です。^^;
/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_

GetRowsの前に普通にレコードセットは作ったのですよね?
今VB5の環境がないのでVB6での話しで書きます。

上の例で言うとarrayのところの変数を例えば
Dim RsArray As Variant
として宣言しておきます。
あと、ADO使うのだったら普通にADOコネクションをOpenしておきます。
DAOでは試してないのでなんなのですが、
とりあえずADOでの説明でご勘弁を。

・・でもってまずは普通にレコードセット作ります。

Dim Rs As ADODB.Recordset
Dim SQL As String

'(ここに取得したいSELECT文のSQL文を書きます)
SQL = "Select なんてらかんてら〜"

Set Rs = New ADODB.Recordset

'Rs作成
'※下記CnはADOコネクションの意味(オープンするコードは略)
Rs.Open SQL, Cn, adOpenStatic, adLockReadOnly, adCmdText

If Rs.EOF Then
  'どうのこうののエラー処理
  Exit Sub
End If

でここまでは普通のレコードセット作りの部分ですね。
で、次にこれをやるわけです。

RsArray = Rs.GetRows()

'いったんRsArrayに格納したのですみやかにRsをクローズしておく
Rs.Close: Set Rs = Nothing

で、それで、いったいどー使うのか?をお聞きになりたいのですよね?

RsArrayの説明:
1)RsArrayは発行されたSelect文に基づくRsを下記Rs.GetRows()でそっくり
配列にしたものです。
2)RsArrayの1次元目はSelect文で選択したフィールドデータが入るが
1番目のフィールドを0から数えます。
3)RsArrayの2次元目はSelect文で選択されたレコード数、つまりロー数を
意味します。
ということなのです。
だから、あ、もうレコードを意のままに操作できるのがみてとれますね。
わかりましたか?

えーーー、
でもどーやって動的にボトムのデータとかを(行数が変動するのにどうやって)
読むのか?質問が来そうですね。
それについてですが、そういうのはLBoundやUBoundを使えばOKなの。
例えば
UBound(RsArray, 2) + 1
とすればそれはレコード数を意味します。

これってまだASPで書いてる方なんかも恩恵ありです。
ASPとASPのルーチン間の連絡なんかに
むりむりPOSTでがんばんなくてもスマートだし、いろいろな局面で応用きくと
思いますよ。

今回の案件には無関係だったにしてもまずはお試しあれ。


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

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






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