第5講 配列の学習

第9話 3次元配列の利用による年間成績一覧表の作成の解説その1

解答例
Public Class Form1

   Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

     '変数の宣言
     Dim i As Integer, j As Integer, w As Integer

     '187行追加
     For i = 1 To 187
       DataGridView1.Rows.Add()
     Next

     For i = 0 To 3
       '見出しを入れる
       If i = 0 Then DataGridView1(0, 47 * i).Value = "1学期"
       If i = 1 Then DataGridView1(0, 47 * i).Value = "2学期"
       If i = 2 Then DataGridView1(0, 47 * i).Value = "3学期"
       If i = 3 Then DataGridView1(0, 47 * i).Value = "1年間"

       '列見出しを入れる。
       DataGridView1(0, 1 + 47 * i).Value = "番号 "
       DataGridView1(1, 1 + 47 * i).Value = "国語 "
       DataGridView1(2, 1 + 47 * i).Value = "社会 "
       DataGridView1(3, 1 + 47 * i).Value = "数学 "
       DataGridView1(4, 1 + 47 * i).Value = "理科 "
       DataGridView1(5, 1 + 47 * i).Value = "英語 "
       DataGridView1(6, 1 + 47 * i).Value = "合計 "
       DataGridView1(7, 1 + 47 * i).Value = "平均 "
       DataGridView1(8, 1 + 47 * i).Value = "最高点"
       DataGridView1(9, 1 + 47 * i).Value = "最低点"
       DataGridView1(10, 1 + 47 * i).Value = "順位 "
       DataGridView1(11, 1 + 47 * i).Value = "合否 "
       DataGridView1(12, 1 + 47 * i).Value = "講評 "

       '行見出し
       DataGridView1(0, 42 + 47 * i).Value = "合計 "
       DataGridView1(0, 43 + 47 * i).Value = "平均 "
       DataGridView1(0, 44 + 47 * i).Value = "最高点"
       DataGridView1(0, 45 + 47 * i).Value = "最低点"
     Next

     '出席番号とランダムデータの発生
     Dim a(3, 39, 6) As Integer, k As Integer
     For i = 0 To 3
       For j = 1 To 40
         a(i, j - 1, 0) = j
       Next
     Next
     For i = 0 To 2
       For j = 1 To 40
         For k = 1 To 5
           a(i, j - 1, k) = Int(101 * Rnd())
         Next
       Next
     Next
 
     '出席番号とランダムデータをDataGridViewに表示させる
     For i = 0 To 3
       For j = 1 To 40
         DataGridView1(0, i * 47 + j + 1).Value = a(i, j - 1, 0)
       Next
     Next
     For i = 0 To 2
       For j = 1 To 40
         For k = 1 To 5
           DataGridView1(k, i * 47 + j + 1).Value = a(i, j - 1, k)
         Next
       Next
    Next

    '各学期合計値・平均値の算出・表示
    For i = 0 To 2
      For j = 1 To 40
        a(i, j - 1, 6) = 0
        For k = 1 To 5
          a(i, j - 1, 6) = a(i, j - 1, 6) + a(i, j - 1, k)
        Next
        DataGridView1(6, i * 47 + j + 1).Value = a(i, j - 1, 6)
        DataGridView1(7, i * 47 + j + 1).Value = a(i, j - 1, 6) / 5
      Next
    Next

    '各学期各生徒の最高点・最低点の算出・表示
    Dim max As Integer, min As Integer
    For i = 0 To 2
      For j = 1 To 40
        max = 0
        min = 100
        For k = 1 To 5
          If a(i, j - 1, k) > max Then max = a(i, j - 1, k)
          If a(i, j - 1, k) < min Then min = a(i, j - 1, k)
        Next
        DataGridView1(8, i * 47 + j + 1).Value = max

  
      DataGridView1(9, i * 47 + j + 1).Value = min
      Next
    Next


            ・
            ・

            ・
   End Sub

End Class

本日は、『//各生徒の合計・平均の算出と表示』までを解説しましょう。
最初に

     '187行追加
     For i = 1 To 187
       DataGridView1.Rows.Add()
     Next

     For i = 0 To 3
       '見出しを入れる
       If i = 0 Then DataGridView1(0, 47 * i).Value = "1学期"
       If i = 1 Then DataGridView1(0, 47 * i).Value = "2学期"
       If i = 2 Then DataGridView1(0, 47 * i).Value = "3学期"
       If i = 3 Then DataGridView1(0, 47 * i).Value = "1年間"

       '列見出しを入れる。
       DataGridView1(0, 1 + 47 * i).Value = "番号 "
       DataGridView1(1, 1 + 47 * i).Value = "国語 "
       DataGridView1(2, 1 + 47 * i).Value = "社会 "
       DataGridView1(3, 1 + 47 * i).Value = "数学 "
       DataGridView1(4, 1 + 47 * i).Value = "理科 "
       DataGridView1(5, 1 + 47 * i).Value = "英語 "
       DataGridView1(6, 1 + 47 * i).Value = "合計 "
       DataGridView1(7, 1 + 47 * i).Value = "平均 "
       DataGridView1(8, 1 + 47 * i).Value = "最高点"
       DataGridView1(9, 1 + 47 * i).Value = "最低点"
       DataGridView1(10, 1 + 47 * i).Value = "順位 "
       DataGridView1(11, 1 + 47 * i).Value = "合否 "
       DataGridView1(12, 1 + 47 * i).Value = "講評 "

       '行見出し
       DataGridView1(0, 42 + 47 * i).Value = "合計 "
       DataGridView1(0, 43 + 47 * i).Value = "平均 "
       DataGridView1(0, 44 + 47 * i).Value = "最高点"
       DataGridView1(0, 45 + 47 * i).Value = "最低点"
     Next
を解説しましょう。この部分で何をしているかと申しますと、

実行結果例
成績一覧表
行の追加
行を作り、そこに見出しを入れています。
For i = 0 To 3となっていますので、
i=0,1,2,3 と同じことが4回繰り返されます。
その結果、1学期、2学期、3学期、1年間
見出し2学期3学期年間
それぞれの見出しが入ります。
注目は、例えばDataGridView1(0, 42 + 47 * i).Value = "合計 "の+ 47 * iの部分です。
行間
学期間の『合計』の位置が47行ずれています。
なので、i=0,1,2,3 とすると、
42+47×0=42
42+47×1=89
42+47×2=136
42+47×0=183
となります。
DataGridView1(*,0)は1行目ですから、43行目・90行目・137行目・184行目に『合計』が表示されることになります。
その他についてもすべて同じです。
例えば、DataGridView1(0, 42 + 47 * i).Value = "合計 " についてみると、
『番号』も47行ごとに表示させています。
47行という数字は、生徒数40から40行、
見出しと列見出し平均2行、
行見出し見出し4行、学期間の空白行3次元配列1行の合計です。
40+2+4+1=47
それぞれ47行ごとに表示させたいとき、42 + 47 * i のようにすればよいわけです。


次に、
     '出席番号とランダムデータの発生
     Dim a(3, 39, 6) As Integer, k As Integer
     For i = 0 To 3
       For j = 1 To 40
         a(i, j - 1, 0) = j
       Next
     Next
     For i = 0 To 2
       For j = 1 To 40
         For k = 1 To 5
           a(i, j - 1, k) = Int(101 * Rnd())
         Next
       Next
     Next
を解説しましょう。最初のDim a(3, 39, 6) As Integer で3次元配列を用意しています。
3は、1学期・2学期・3学期・1年間の4つに対応します。
a(3)とした場合a(0),a(1),a(2),a(3)までが配列変数の対象になります。
VC++の場合はa[0],a[1],a[2],a[3]としたいときは、int a[4]; ですが、VBのa(3)の3は最後の添え字を示しています。
次の39は、生徒数40に対応しています。
最後の6は、出席番号・国語・社会・数学・理科・英語・合計の7つに対応しています。
平均までを対象にしなかったのは、平均だけ整数でないからです。
こちらは浮動小数点型になります。
キャストなどをして対象にする方法も考えられますが、面倒なので合計までを配列で扱い処理することにしました。
     For i = 0 To 3
       For j = 1 To 40
         a(i, j - 1, 0) = j
       Next
     Next

     For i = 0 To 3
       For j = 0 To 39
         a(i, j - 1, 0) = j + 1
       Next
     Next
としてもいいですが、jを出席番号に対応させた方がわかりやすいと考え前者を選びました。
ですが、この辺は各自の好みです。ご自分がわかりやすい方を選んでください。
この3行では、3次元配列をa(学期等,行,列)と表現するとすれば、各学期の0列目の0行目から39行目まで順に出席番号を入れています。

     For i = 0 To 2
       For j = 1 To 40
         For k = 1 To 5
           a(i, j - 1, k) = Int(101 * Rnd())
         Next
       Next
     Next
では、100点以下のランダムデータを配列に収納しています。
Rnd()は、1未満のの乱数を発生させます。
ですから101 * Rnd()は101未満の小数で、
その小数分を Int()で切り捨てて、101未満の整数すなわち100以下の整数になります。

     '出席番号とランダムデータをDataGridViewに表示させる
     For i = 0 To 3
       For j = 1 To 40
         DataGridView1(0, i * 47 + j + 1).Value = a(i, j - 1, 0)
       Next
     Next
     For i = 0 To 2
       For j = 1 To 40
         For k = 1 To 5
           DataGridView1(k, i * 47 + j + 1).Value = a(i, j - 1, k)
         Next
       Next
    Next
では、配列に収まっている出席番号と各教科のランダムデータをDataGridView1に表示させています。
DataGridView1(0, i * 47 + j + 1).Value = a(i, j - 1, 0) は3次元配列を2次元配列に対応させています。
その際の味噌は
47*i+j+1です。
47 * i + j + 1は、j + 1 + 47 * i と同じです。

実は、3次元データは、2次元でも1次元でも表現できます。
言い換えると、3次元配列は、2次元配列や1次元配列に対応させることができます。

同様に、2次元配列は1次元配列で表現できます。
例えば、
Dim a(2,3) As Integer,b(11) As integer,i As Integer,j As Integer;
For i = 0 To 11
  b(i) = Int(101 * Rad())
Next
For i = 0 To 2
  For j = 0 To 3
    a(i, j) = b(4 * i + j)
  Next
Next
とプログラミングすれば、1次元配列b(11)の12個のランダムデータを2次元配列a(2,3)に収納させたことになります。
a(i, j) = b(4 * i + j) の対応を具体的に見てみましょう。
a(0, 0)=b(0), a(0, 1)=b(1), a(0, 2)=b(2), a(0, 3)=b(3),
a(1, 0)=b(4), a(1, 1)=b(5), a(1, 2)=b(6), a(1, 3)=b(7),
a(2, 0)=b(8), a(2, 1)=b(9), a(2, 1)=b(10), a(2, 3)=b(11)
2次元配列a(
2, 3)の12((+1)×(+1))個の変数と1次元配列b(11)の12(11+1)個の変数がきれいに対応しています。
()内で+1としているのは、添え字0も数えなければならないからです。
ここでの味噌は、4*i+jです。動きを表にすると、

i j 4*i+j
0 0 0
0 1 1
0 2 2
0 3 3
1 0 4
1 1 5
1 2 6
1 3 7
2 0 8
2 1 9
2 2 10
2 3 11


例えば、i=2,j=3なら
4*i+j=4×2+3=11
です。
4*i+jの4は、 a(2,
3)の3+1=4(添え字0も数える)に対応しています。

For i=0 To 2
  For j=0 To 3
    a(i, j)=Int(101 * Rad())
  Next
Next
として、それをb(11)に収めたいなら、
For i=0 To 2
  For j=0 To 3
    b(4 * i + j)=a(i, j)
  Next
Next
このように2次元配列を1次元配列に、
1次元配列を2次元配列に対応させることができます。
すなわち、1次元配列と2次元配列は相互に対応させることができるのです。


DataGridView1(k, i * 47 + j + 1).Value = a(i, j - 1, k)
においては3次元データを2次元配列に代入しています。

47 * i+ j + 1と(i,j - 1)が対応します。
今の例の
4 * i + jと(i, j)の対応と同様です。4 * iの4はa(2,
3)の3に1加えたものでした。
DataGridView1の場合は、a(3, 39, 6) の39に1加えた40に、見出しと列見出し2行、行見出し4行、空白行1行を加えた47です。
見出しと列見出し2行、行見出し4行、空白行1行がなければ、a(3, 39, 6) の39に1加えた40にきれいに対応するのです。

尚、参考までに述べておくと
For i=0 To 2
  For j=0 To 3
    b(4 * i + j)=a(i, j)
  Next
Next
は、
For i=0 To 11
  b(i)=(Int(i / 4),i mod 4)
Next
でも実現できます。
Int(i / 4)のIntは小数部分を切り捨てよの命令ですから
例えば、i=7ならInt(7/4)=1です。
まは、i mod 4はiを4で割った余りを求める計算です。
したがいまして、i mod 4は7 mod 4=3です。
ですから
b(7)=a(1,3)です。上の表で対応が正しいことをご確認ください。



    '各学期合計値・平均値の算出・表示
    For i = 0 To 2
      For j = 1 To 40
        a(i, j - 1, 6) = 0
        For k = 1 To 5
          a(i, j - 1, 6) = a(i, j - 1, 6) + a(i, j - 1, k)
        Next
        DataGridView1(6, i * 47 + j + 1).Value = a(i, j - 1, 6)
        DataGridView1(7, i * 47 + j + 1).Value = a(i, j - 1, 6) / 5
      Next
    Next

では、合計を計算して、合計と平均を表示しています。
a(i, j - 1, 6)が合計です。
a(i , j - 1 , 6)=0を忘れないでください。
これは初期化です。

    '各学期各生徒の最高点・最低点の算出・表示
    Dim max As Integer, min As Integer
    For i = 0 To 2
      For j = 1 To 40
        max = 0
        min = 100
        For k = 1 To 5
          If a(i, j - 1, k) > max Then max = a(i, j - 1, k)
          If a(i, j - 1, k) < min Then min = a(i, j - 1, k)
        Next
        DataGridView1(8, i * 47 + j + 1).Value = max

  
      DataGridView1(9, i * 47 + j + 1).Value = min
      Next
    Next
では各生徒の最高点・最低点を計算し表示しています。ここでも i * 47 + j + 1が理解できれば難しくありません。


第8話へ 第10話へ

006

VC++講義第1部へ
vb講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座

数学研究室に戻る