DOBON.NET DOBON.NETプログラミング掲示板過去ログ

1次元配列の引数に2次元配列を渡したい

環境/言語:[VS2005]
分類:[.NET]

VB.Net2005で分からないことがあり、Webで調べましたが解決できません。
ご教授お願いします。

Private Sub AAA(Buf As Byte())

End Sub
のようなプロシージャがあるとして
Dim Buf2(10,256) As Byte  '要素数256のByte配列を10個用意するという意味
としたときに
上記プロシージャにループの中で0番目から9番目の256Byte配列を順に渡したいのですが
やり方が分かりません。ちなみに、上記AAAプロシージャは自作で無いので書き換えは
できない状況です。
よろしくお願いします。
新しく配列を作ってコピーしてください。
多次元配列だといろいろ面倒でしょうけど、数値などのプリミティブ型なら Buffer.BlockCopy が多次元配列相手でも使えますかね。

> Dim Buf2(10,256) As Byte '要素数256のByte配列を10個用意するという意味
多次元配列は配列の配列(ジャグ配列)とは別物なので、「要素数 m の Byte 配列を n 個」という意味ではありません。
ジャグ配列なら、今回の要望は簡単に満たすことができるでしょう。詳しくはまず検索してみてください。
これに限らず多次元配列は扱いが面倒なことが多いので、できる限りジャグ配列で代用することをお勧めします。
ところで、この宣言だと一次元目は要素数 11 で二次元目は要素数 257 になりますよ。
素早い回答感謝いたします。
「ジャグ配列」について、これから調査してみます。
要素数の間違いはうっかりでした。失礼しました。
ありがとうございます。
ひで46さん
ArrayクラスのCopyメソッドを使うことはできませんか?
できません。Array.Copy はコピー元とコピー先の次元が同じである必要があります。
// これも多次元配列の「扱いが面倒」の一つですね。
Hongliangさん
> できません。Array.Copy はコピー元とコピー先の次元が同じである必要があります。
> // これも多次元配列の「扱いが面倒」の一つですね。
申し訳無いです。
確かに次元が一致して無いと駄目ですね。
次元をあわせると、a(1,9)
を B(0,18)にコピーできるのですが。

ひで46さん
混乱させて申し訳無いです。
2009/03/13(Fri) 13:35:38 編集(投稿者)

■No24188に返信(きいよさんの記事)
>>できません。Array.Copy はコピー元とコピー先の次元が同じである必要があります。
> 申し訳無いです。
> 確かに次元が一致して無いと駄目ですね。

Array.Copy ではなく、Marshal.Copy( IntPtr, Byte( ), Integer, Integer ) ならば
Byte( , ) → IntPtr → Byte( ) にて転送できる事を確認できました。
分かりにくい上、ポインタ操作になるのでお奨めはできませんけれども。

個人的には、
 (案1) 単純に、2次元配列から 1 次元配列に、1次元ずつループでコピーする。
 (案2) 2次元配列で管理するのをやめ、List( Of T ) や ジャグ配列で管理。
 (案3) Sub AAA側の実装を Sub AAA( ary( , ) As Byte, x As Integer ) に変更。
あたりが妥当な方法かと思います。
みなさん、色々アドバイスありがとうございます。
ジャグ配列でやりたいのですが、うまくできていません。
(テストコードを書いてみて要素数固定でジャグ配列の使い方は理解できました)

実は1次元配列側の要素数、その配列の個数(要素数)共に
動的に変えたいのです。

Redimで変更できるのは配列の個数(要素数)だけのようで
Redim(m)()はできますが、Redim(m)(n)のように書けません。

C言語で2次元配列の一部を渡したいときはポインタで簡単に
できるので、VB.netでも良い方法があるように思うのですが。
> Redimで変更できるのは配列の個数(要素数)だけのようで
> Redim(m)()はできますが、Redim(m)(n)のように書けません。
ジャグ配列は、配列内の配列をそれぞれ初期化する必要があります。
New を使って初期化してください。
Dim a(m)()
For i As Byte= 0 To m
    a(i) = New Byte(n) { }
Next

> C言語で2次元配列の一部を渡したいときはポインタで簡単に
> できるので、VB.netでも良い方法があるように思うのですが。
VB は C 言語ではないので。
■No24190に返信(ひで46さんの記事)
> (テストコードを書いてみて要素数固定でジャグ配列の使い方は理解できました)

あれ? 要素数固定の配列は、VB.NET では作れないと思いますが…。
(VB6 や C# であれば作れますが)

次元数は固定的ですが、要素数は常に動的に変化させられるはず。
現在は、どのようなコードを書いているのでしょうか?


> 実は1次元配列側の要素数、その配列の個数(要素数)共に
> 動的に変えたいのです。
List(Of Byte())、または List(Of List(Of Byte)) で管理するという手も。


> Redimで変更できるのは配列の個数(要素数)だけのようで
> Redim(m)()はできますが、Redim(m)(n)のように書けません。

Module Module1

    Sub Main()
        Dim a()() As Byte = { _
            New Byte() {1, 2, 3}, _
            New Byte() {4, 5}, _
            New Byte() {6, 7, 8, 9} _
        }

        Dump(a)

        ReDim Preserve a(6)
        a(3) = New Byte() {}
        a(5) = New Byte() {15, 31, 63, 127, 255}
        ReDim a(6)(2)
        a(6)(0) = 1
        a(6)(1) = 5
        a(6)(2) = 3

        Dump(a)

        ReDim Preserve a(1)(3)
        a(1)(3) = 255

        Dump(a)

        Console.ReadKey()
    End Sub

    Sub Dump(ByVal o()() As Byte)
        For n As Integer = 0 To UBound(o)
            Console.Write("{0}:", n)
            Dim item() As Byte = o(n)
            If item Is Nothing Then
                Console.WriteLine("(null)")
            Else
                Console.WriteLine(BitConverter.ToString(item))
            End If
        Next
        Console.WriteLine("---------")
    End Sub
End Module
ありがとうございます。
色々試行錯誤しまして、

Redim a(m)          '配列の個数を変更
ReDim Ary(n)        '次元配列の要素数を変更
For i = 0 To m      'このループで要素数nの1次元配列をm個用意
    a(i) = Ary.Clone
Next

という処理を考えましたが、Hongliangさんの方式が良いですね。
ジャグ配列を使ってもこのような形にするしかないことが分かりました。
とりあえず、これで前に進めます。ありがとうございました。
解決済み!
魔界の仮面弁士さん、いつもすばらしい回答を拝見しております。
投稿タイミングが重なってしまったようで、失礼しました。

> あれ? 要素数固定の配列は、VB.NET では作れないと思いますが…。
> (VB6 や C# であれば作れますが)
すいません。要素数固定という表現がまずかったです。
コード中の初期化で要素を入れるという動作が確認できたという意味です。
私がやりたかったのはまさに、Hongliangの示して頂いたコードでした。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板