tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトル入れ子の構造体へのバイト配列のセットについて
記事No10939
投稿日: 2012/11/03(Sat) 07:54
投稿者九州男児
VB.Netの経験が浅く困っています。ご教授願います。

下記のような構造体があります。

Public Structure pcKIROKU <========構造体の指定(A)
    Public Shared KYOBI1 As Byte() = New Byte(27) {}
    Public Shared KZokusei As Byte
    Public Shared IkisakiCd As Byte
    Public Shared KTutatuNo() As Byte = New Byte(1) {}
    Public Shared KTatuHkb() As Byte = New Byte(2) {}
    Public Shared KSekobi() As Byte = New Byte(2) {}
    Public Shared KSigyoKumi As Byte() = New Byte(10) {}
    Public Shared KSigyoNo() As Byte = New Byte(1) {}
    Public Shared KKushoCd As Byte
    Public Sub Initialize()
    End Sub
    End Sub
End Structure

Sub Main()
    Dim mcKIROKU(15) As pcKIROKU <===========上記(A)を使用して構造体定義(15)
    mcKIROKU.Initialize()
    Erase mcKIROKU
    ReDim mcKIROKU(15)

    ******************** 構造体と同じ長さのバイナリの読み込み
    Dim fs As FileStream
    Dim br As BinaryReader
    Dim buf(mcKIROKU_Byte) As Byte
    Dim ec As System.Text.Encoding = System.Text.Encoding.ASCII
    fs = New FileStream("C:\aaa.bin", FileMode.Open, FileAccess.Read)
    br = New BinaryReader(fs)
    br.BaseStream.Seek(9, SeekOrigin.Begin)
    ReDim buf(mcKIROKU_Byte)
    br.Read(buf, 0, mcKIROKU_Byte)
    fs.Close()

    上記のbuf(バイナリデータ)を構造体(mcKIROKU)の先頭から順に代入したいのですが
    色々調べて試しましたが、うまくいきません。
    (次のバイナリを読み込んだら次の構造体mcKIROKU(1)に代入)
    また、構造体を参照(mcKIROKU(0).KSekobi)しようとすると。
    <インスタンスを経由する共有メンバへのアクセスです。正規の式は評価されません。>
    の警告が出てしまいます。
    
    だれかご存知の方がいたらご教授ください。

[ツリー表示へ]
タイトルRe: 入れ子の構造体へのバイト配列のセットについて
記事No10942
投稿日: 2012/11/03(Sat) 18:12
投稿者YuO
> Public Structure pcKIROKU <========構造体の指定(A)
>     Public Shared KYOBI1 As Byte() = New Byte(27) {}
>     Public Shared KZokusei As Byte
>     Public Shared IkisakiCd As Byte
>     Public Shared KTutatuNo() As Byte = New Byte(1) {}
>     Public Shared KTatuHkb() As Byte = New Byte(2) {}
>     Public Shared KSekobi() As Byte = New Byte(2) {}
>     Public Shared KSigyoKumi As Byte() = New Byte(10) {}
>     Public Shared KSigyoNo() As Byte = New Byte(1) {}
>     Public Shared KKushoCd As Byte
>     Public Sub Initialize()
>     End Sub
>     End Sub
> End Structure

なぜ、すべてのフィールドに「Shared」が付いているのですか。
使い方を見るに,Sharedは不要だと思いますが。

>     <インスタンスを経由する共有メンバへのアクセスです。正規の式は評価されません。>
>     の警告が出てしまいます。

Sharedのついているメンバは,(構造体/クラス名).メンバ名でアクセスします。

[ツリー表示へ]
タイトルRe^2: 入れ子の構造体へのバイト配列のセットについて
記事No10943
投稿日: 2012/11/03(Sat) 18:44
投稿者九州男児
> > Public Structure pcKIROKU <========構造体の指定(A)
> >     Public Shared KYOBI1 As Byte() = New Byte(27) {}
> >     Public Shared KZokusei As Byte
> >     Public Shared IkisakiCd As Byte
> >     Public Shared KTutatuNo() As Byte = New Byte(1) {}
> >     Public Shared KTatuHkb() As Byte = New Byte(2) {}
> >     Public Shared KSekobi() As Byte = New Byte(2) {}
> >     Public Shared KSigyoKumi As Byte() = New Byte(10) {}
> >     Public Shared KSigyoNo() As Byte = New Byte(1) {}
> >     Public Shared KKushoCd As Byte
> >     Public Sub Initialize()
> >     End Sub
> >     End Sub
> > End Structure
>
> なぜ、すべてのフィールドに「Shared」が付いているのですか。
> 使い方を見るに,Sharedは不要だと思いますが。
>
> >     <インスタンスを経由する共有メンバへのアクセスです。正規の式は評価されません。>
> >     の警告が出てしまいます。
>
> Sharedのついているメンバは,(構造体/クラス名).メンバ名でアクセスします。

ご指摘ありがとうございます。
Newでサイズを指定した場合、「Shared」をつけないとエラーになったのですが。
また、また、Dim mcKIROKU(15) As pcKIROKUで2次元(入れ子?)にしている為、
(構造体).メンバ名では意図した値が返ってきません。
.Net初心者で申し訳ありません。
やりたい事は2次元の構造体に読み込んだデータ(レコード)を入れて参照、更新したいのですが。

[ツリー表示へ]
タイトルRe^3: 入れ子の構造体へのバイト配列のセットについて
記事No10946
投稿日: 2012/11/06(Tue) 23:06
投稿者魔界の仮面弁士
> Public Shared KYOBI1 As Byte() = New Byte(27) {}
> Public Shared KTutatuNo() As Byte = New Byte(1) {}

「Dim var() As Type」か
「Dim var As Type()」かを統一しましょう。
どちらも同じ意味とはいえ、混在しているのは見苦しいので。

なお、VBでは前者の書き方が標準的です。



> Newでサイズを指定した場合、「Shared」をつけないとエラーになったのですが。
この場面で、Shared を使うべきではありません。たとえば、
    Dim a As pcKIROKU, b As pcKIROKU
    a.KYOBI1(0) = 10
    b.KYOBI1(0) = 20
    a.KZokusei = 100
    b.KZokusei = 200
のような使い方をしたいなら、Shared は使えないことになります。

Shared にすると、構造体変数ではなく構造体そのもので値が管理されるため、
上記 a と b とで、異なる値を保持することができなくなるためです。

Dim mcKIROKU(15) As pcKIROKU のように、配列で管理した場合も同様です。
KZokusei が Shared の場合、mcKIROKU(0).KZokusei や mcKIROKU(1).KZokusei は、
結局は「pcKIROKU.KZokusei」の意味になってしまいます。


初期サイズを設定したいなら、
    (案1) 構造体の代わりにクラスで代用する。
    (案2) 引数付コンストラクタを用意し、そこで配列サイズを初期化する。
    (案3) 現在未使用の Initialize メソッドを利用して、そこで配列サイズを初期化する。
    (案4) VB の代わりに unsafe C# を採用し、fixed (固定サイズの配列)を指定する。
などの手法で代用してみてください。


案1
Public Class pcKIROKU2
    Public KYOBI1(27) As Byte
    Public KZokusei As Byte
    Public IkisakiCd As Byte
    Public KTutatuNo(1) As Byte
    Public KTatuHkb(2) As Byte
    Public KSekobi(2) As Byte
    Public KSigyoKumi(10) As Byte
    Public KSigyoNo(1) As Byte
    Public KKushoCd As Byte
End Class

この方法の場合、使う前に New する必要が生じます。
たとえば
 Dim a As New pcKIROKU()
 Dim b() As pcKIROKU = { New pcKIROKU(), New pcKIROKU()}
など。

New しなかった場合は、クラス変数が Nothing となるため、
そのまま使うと NullReferenceException の原因となります。



案2
Public Structure pcKIROKU
    Public KYOBI1() As Byte
    Public KZokusei As Byte
    Public IkisakiCd As Byte
    Public KTutatuNo() As Byte
    Public KTatuHkb() As Byte
    Public KSekobi() As Byte
    Public KSigyoKumi() As Byte
    Public KSigyoNo() As Byte
    Public KKushoCd As Byte

    Public Sub New(dummy As Integer)
        ReDim KYOBI1(27), KTutatuNo(1)
        ReDim KTatuHkb(2), KSekobi(2)
        ReDim KSigyoKumi(10), KSigyoNo(1)
    End Sub
End Structure

この方法の場合、使う前に New する必要が生じます。
たとえば
 Dim a As New pcKIROKU(0)
 Dim b() As pcKIROKU = { New pcKIROKU(1), New pcKIROKU(2)}
など。

New しなかった場合は、構造体変数が初期値のままとなるため
各フィールドの配列もまた、初期化されていない状態となります。



案3
Public Structure pcKIROKU
    Public KYOBI1() As Byte
    Public KZokusei As Byte
    Public IkisakiCd As Byte
    Public KTutatuNo() As Byte
    Public KTatuHkb() As Byte
    Public KSekobi() As Byte
    Public KSigyoKumi() As Byte
    Public KSigyoNo() As Byte
    Public KKushoCd As Byte

    Public Sub Initialize()
        ReDim KYOBI1(27), KTutatuNo(1)
        ReDim KTatuHkb(2), KSekobi(2)
        ReDim KSigyoKumi(10), KSigyoNo(1)
    End Sub
End Structure

この方法の場合、使う前に Initialize メソッドを呼ぶ必要が生じます。
たとえば
 Dim a As pcKIROKU
 Dim b(1) As pcKIROKU
 a.Initilaize()
 b(0).Initilaize()
 b(1).Initilaize()
など。

Initialize を呼ばなかった場合は、構造体変数が初期値のままとなるため
各フィールドの配列もまた、初期化されていない状態となります。


案4
public unsafe struct pcKIROKU
{
    public fixed byte KYOBI1[28];
    public byte KZokusei;
    public byte IkisakiCd;
    public fixed byte KTutatuNo[2];
    public fixed byte KTatuHkb[3];
    public fixed byte KSekobi[3];
    public fixed byte KSigyoKumi[11];
    public fixed byte KSigyoNo[2];
    public byte KKushoCd;
}


> やりたい事は2次元の構造体に読み込んだデータ(レコード)を入れて参照、更新したいのですが。
二次元なら、たとえば
 Dim mcKIROKU(2, 3) As pcKIROKU
のような宣言になるでしょうね。


データレコードの管理ならば、DataTable を使う手法もあります。

[ツリー表示へ]
タイトルRe^4: 入れ子の構造体へのバイト配列のセットについて
記事No10957
投稿日: 2012/11/18(Sun) 11:50
投稿者九州男児
> > Public Shared KYOBI1 As Byte() = New Byte(27) {}
> > Public Shared KTutatuNo() As Byte = New Byte(1) {}
>
> 「Dim var() As Type」か
> 「Dim var As Type()」かを統一しましょう。
> どちらも同じ意味とはいえ、混在しているのは見苦しいので。
>
> なお、VBでは前者の書き方が標準的です。
>
>
>
> > Newでサイズを指定した場合、「Shared」をつけないとエラーになったのですが。
> この場面で、Shared を使うべきではありません。たとえば、
>     Dim a As pcKIROKU, b As pcKIROKU
>     a.KYOBI1(0) = 10
>     b.KYOBI1(0) = 20
>     a.KZokusei = 100
>     b.KZokusei = 200
> のような使い方をしたいなら、Shared は使えないことになります。
>
> Shared にすると、構造体変数ではなく構造体そのもので値が管理されるため、
> 上記 a と b とで、異なる値を保持することができなくなるためです。
>
> Dim mcKIROKU(15) As pcKIROKU のように、配列で管理した場合も同様です。
> KZokusei が Shared の場合、mcKIROKU(0).KZokusei や mcKIROKU(1).KZokusei は、
> 結局は「pcKIROKU.KZokusei」の意味になってしまいます。
>
>
> 初期サイズを設定したいなら、
>     (案1) 構造体の代わりにクラスで代用する。
>     (案2) 引数付コンストラクタを用意し、そこで配列サイズを初期化する。
>     (案3) 現在未使用の Initialize メソッドを利用して、そこで配列サイズを初期化する。
>     (案4) VB の代わりに unsafe C# を採用し、fixed (固定サイズの配列)を指定する。
> などの手法で代用してみてください。
>
>
> 案1
> Public Class pcKIROKU2
>     Public KYOBI1(27) As Byte
>     Public KZokusei As Byte
>     Public IkisakiCd As Byte
>     Public KTutatuNo(1) As Byte
>     Public KTatuHkb(2) As Byte
>     Public KSekobi(2) As Byte
>     Public KSigyoKumi(10) As Byte
>     Public KSigyoNo(1) As Byte
>     Public KKushoCd As Byte
> End Class
>
> この方法の場合、使う前に New する必要が生じます。
> たとえば
>  Dim a As New pcKIROKU()
>  Dim b() As pcKIROKU = { New pcKIROKU(), New pcKIROKU()}
> など。
>
> New しなかった場合は、クラス変数が Nothing となるため、
> そのまま使うと NullReferenceException の原因となります。
>
>
>
> 案2
> Public Structure pcKIROKU
>     Public KYOBI1() As Byte
>     Public KZokusei As Byte
>     Public IkisakiCd As Byte
>     Public KTutatuNo() As Byte
>     Public KTatuHkb() As Byte
>     Public KSekobi() As Byte
>     Public KSigyoKumi() As Byte
>     Public KSigyoNo() As Byte
>     Public KKushoCd As Byte
>
>     Public Sub New(dummy As Integer)
>         ReDim KYOBI1(27), KTutatuNo(1)
>         ReDim KTatuHkb(2), KSekobi(2)
>         ReDim KSigyoKumi(10), KSigyoNo(1)
>     End Sub
> End Structure
>
> この方法の場合、使う前に New する必要が生じます。
> たとえば
>  Dim a As New pcKIROKU(0)
>  Dim b() As pcKIROKU = { New pcKIROKU(1), New pcKIROKU(2)}
> など。
>
> New しなかった場合は、構造体変数が初期値のままとなるため
> 各フィールドの配列もまた、初期化されていない状態となります。
>
>
>
> 案3
> Public Structure pcKIROKU
>     Public KYOBI1() As Byte
>     Public KZokusei As Byte
>     Public IkisakiCd As Byte
>     Public KTutatuNo() As Byte
>     Public KTatuHkb() As Byte
>     Public KSekobi() As Byte
>     Public KSigyoKumi() As Byte
>     Public KSigyoNo() As Byte
>     Public KKushoCd As Byte
>
>     Public Sub Initialize()
>         ReDim KYOBI1(27), KTutatuNo(1)
>         ReDim KTatuHkb(2), KSekobi(2)
>         ReDim KSigyoKumi(10), KSigyoNo(1)
>     End Sub
> End Structure
>
> この方法の場合、使う前に Initialize メソッドを呼ぶ必要が生じます。
> たとえば
>  Dim a As pcKIROKU
>  Dim b(1) As pcKIROKU
>  a.Initilaize()
>  b(0).Initilaize()
>  b(1).Initilaize()
> など。
>
> Initialize を呼ばなかった場合は、構造体変数が初期値のままとなるため
> 各フィールドの配列もまた、初期化されていない状態となります。
>
>
> 案4
> public unsafe struct pcKIROKU
> {
>     public fixed byte KYOBI1[28];
>     public byte KZokusei;
>     public byte IkisakiCd;
>     public fixed byte KTutatuNo[2];
>     public fixed byte KTatuHkb[3];
>     public fixed byte KSekobi[3];
>     public fixed byte KSigyoKumi[11];
>     public fixed byte KSigyoNo[2];
>     public byte KKushoCd;
> }
>
>
> > やりたい事は2次元の構造体に読み込んだデータ(レコード)を入れて参照、更新したいのですが。
> 二次元なら、たとえば
>  Dim mcKIROKU(2, 3) As pcKIROKU
> のような宣言になるでしょうね。
>
>
> データレコードの管理ならば、DataTable を使う手法もあります。



ありがとうございました。

おかげさまで解決しました。

[ツリー表示へ]