第8講 Functionプロシージャ

第3話 成績一覧表作成ソフトのプロシージャによる改良
前話問題解答例
Public Class Form1
   Dim a(3, 39, 6) As Integer
   Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

     '187行追加
     f1()

     '見出しを入れる
     f2()

     '出席番号とランダムデータの発生
     f3()

     '出席番号とランダムデータをDataGridViewに表示させる
     f4()

     '各学期合計値・平均値の算出・表示
     f5()

      '各学期各生徒の最高点・最低点の算出・表示
     f6()

     '各学期合否・講評の算出・表示
     f7()

     '各学期各教科の合計・平均の算出・表示
     f8()

     '各学期各教科の最高点・算出の算出・表示
     f9()

     '各学期の並び替え
     f10()

     '各学期順位付け
     f11()

     '各学期出席番号順並び替え
     f12()

   End Sub

   '187行追加
   Sub f1()
     Dim i As Integer
     For i = 1 To 187
       DataGridView1.Rows.Add()
     Next
   End Sub

   '見出しを入れる
   Sub f2()
     Dim i As Integer
     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
   End Sub

   '出席番号とランダムデータの発生
   Sub f3()
     Dim 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
   End Sub

   '出席番号とランダムデータをDataGridViewに表示させる
   Sub f4()
     Dim i As Integer, j As Integer
     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
   End Sub

   '各学期合計値・平均値の算出・表示
   Sub f5()
     Dim i As Integer, j As Integer
     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
   End Sub

   '各学期各生徒の最高点・最低点の算出・表示
   Sub f6()
     Dim i As Integer, j As Integer
     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

   '各学期合否・講評の算出・表示
   Sub f7()
     Dim i As Integer, j As Integer
     For i = 0 To 2
       For j = 1 To 40
         If a(i, j - 1, 6) >= 250 Then DataGridView1(11, i * 47 + j + 1).Value = "合格"
         If a(i, j - 1, 6) < 250 Then DataGridView1(11, i * 47 + j + 1).Value = "不合格"
       Next
       For j = 1 To 40
         If a(i, j - 1, 6) >= 350 Then DataGridView1(12, i * 47 + j + 1).Value = "上位合格です。"
         If a(i, j - 1, 6) < 350 And a(i, j - 1, 6) >= 280 Then DataGridView1(12, i * 47 + j + 1).Value = "余裕で合格です。"
         If a(i, j - 1, 6) < 280 And a(i, j - 1, 6) >= 250 Then DataGridView1(12, i * 47 + j + 1).Value = "ぎりぎり合格です。"
         If a(i, j - 1, 6) < 250 And a(i, j - 1, 6) >= 230 Then DataGridView1(12, i * 47 + j + 1).Value = "合格まで後一歩です。"
         If a(i, j - 1, 6) < 230 Then DataGridView1(12, i * 47 + j + 1).Value = "よく勉強して再挑戦!"
       Next
     Next
   End Sub

   '各学期各教科の合計・平均の算出・表示
   Sub f8()
     Dim i As Integer, j As Integer, w As Integer
     For i = 0 To 2
       For j = 1 To 6
         w = 0
         For k = 1 To 40
           w = w + a(i, k - 1, j)
         Next
         DataGridView1(j, i * 47 + 42).Value = w
         DataGridView1(j, i * 47 + 43).Value = w / 40
       Next
       DataGridView1(7, i * 47 + 42).Value = DataGridView1(6, i * 47 + 42).Value / 5
       DataGridView1(7, i * 47 + 43).Value = DataGridView1(7, i * 47 + 42).Value / 40
     Next
   End Sub

    '各学期各教科の最高点・算出の算出・表示
   Sub f9()
     Dim i As Integer, j As Integer
     Dim max As Integer, min As Integer
     For i = 0 To 2
       For j = 1 To 6
         max = 0
         min = 500
         For k = 1 To 40
           If a(i, k - 1, j) > max Then max = a(i, k - 1, j)
           If a(i, k - 1, j) < min Then min = a(i, k - 1, j)
         Next
         DataGridView1(j, i * 47 + 44).Value = max
         DataGridView1(j, i * 47 + 45).Value = min
       Next
     Next
   End Sub

  '各学期の並び替え
   Sub f10()
     Dim i As Integer, j As Integer
     Dim bn As Integer, w1 As String, w As Integer
     Dim min As Integer
     For i = 0 To 2
       For j = 40 To 2 Step -1
         min = 500
         For k = 1 To j
           If a(i, k - 1, 6) < min Then
             min = a(i, k - 1, 6)
             bn = k
           End If
         Next
         For k = 0 To 6
           w = a(i, bn - 1, k)
           a(i, bn - 1, k) = a(i, j - 1, k)
           a(i, j - 1, k) = w
         Next
         For k = 0 To 12
           w1 = DataGridView1(k, i * 47 + bn + 1).Value
           DataGridView1(k, i * 47 + bn + 1).Value = DataGridView1(k, i * 47 + j + 1).Value
           DataGridView1(k, i * 47 + j + 1).Value = w1
         Next
       Next
     Next
   End Sub

   '各学期順位付け
   Sub f11()
     Dim i As Integer, j As Integer
     For i = 0 To 2
       For j = 1 To 40
         DataGridView1(10, i * 47 + j + 1).Value = j
       Next
       For j = 2 To 40
         If a(i, j - 1, 6) = a(i, j - 2, 6) Then DataGridView1(10, i * 47 + j + 1).Value = DataGridView1(10, i * 47 + j).Value
       Next
     Next
   End Sub

   '各学期出席番号順並び替え
   Sub f12()
     Dim i As Integer, j As Integer, k As Integer, bn As Integer, w As Integer
     Dim w1 As String
     Dim max As Integer

     For i = 0 To 2
       For j = 40 To 2 Step -1
         max = 0
         For k = 1 To j
           If a(i, k - 1, 0) > max Then
             max = a(i, k - 1, 0)
             bn = k
           End If
         Next
         For k = 0 To 6
           w = a(i, bn - 1, k)
           a(i, bn - 1, k) = a(i, j - 1, k)
           a(i, j - 1, k) = w
         Next
         For k = 0 To 12
           w1 = DataGridView1(k, i * 47 + bn + 1).Value
           DataGridView1(k, i * 47 + bn + 1).Value = DataGridView1(k, i * 47 + j + 1).Value
           DataGridView1(k, i * 47 + j + 1).Value = w1
         Next
       Next
     Next
   End Sub

End Class

今回は、すべてSubプロシージャでしたが、合計を求める部分などをFunctionプロシージャにさせてプログラムをもっともっとすっきりしたものにしましょう。
例えば、出席番号順に並び直すことを任務にするf12は、3次元ループになっていてわかりにくいですね。
そこで、f12を次のようにしたらどうでしょうか。
   Sub f12()
    Dim i As Integer, j As Integer
    For i = 0 To 2
      For j = 40 To 2 Step -1
       h12(i, j, g12(i, j))
      Next
    Next
   End Sub

   Function g12(ByVal p As Integer, ByVal q As Integer) As Integer
     Dim i As Integer, bn As Integer, max As Integer
     max = 0
     For i = 1 To q
       If a(p, i - 1, 0) > max Then
         max = a(p, i - 1, 0)
         bn = i
       End If
     Next
     Return bn
   End Function

   Sub h12(ByVal p As Integer, ByVal q As Integer, ByVal bn As Integer)
     Dim i As Integer, w As Integer, w1 As String
     For i = 0 To 6
       w = a(p, bn - 1, i)
       a(p, bn - 1, i) = a(p, q - 1, i)
       a(p, q - 1, i) = w
     Next
     For i = 0 To 12
       w1 = DataGridView1(i, p * 47 + bn + 1).Value
       DataGridView1(i, p * 47 + bn + 1).Value = DataGridView1(i, p * 47 + q + 1).Value
       DataGridView1(i, p * 47 + q + 1).Value = w1
    Next
   End Sub
g12はbnを返すFunctionプロシージャです。
   Sub f12()
    Dim i As Integer, j As Integer, k As Integer, w As Integer, w1 As String
    For i = 0 To 2
      For j = 40 To 2 Step -1
       h12(i, j, g12(i, j))
      Next
    Next
   End Sub
h12(i, j, g12(i, j))は非常にわかりにくいですね。
次のようにコードを変更した方がわかりやすいでしょうか。
   Sub f12()
    Dim i As Integer, j As Integer, k As Integer, w As Integer, w1 As String, x As Integer
    For i = 0 To 2
      For j = 40 To 2 Step -1
       x = g12(i, j)
       h12(i, j, x)
      Next
    Next
   End Sub
g12(i, j)はbnを求める関数でしたね。
bnとは何かと申しますと、対象範囲の出席番号のもっとも大きい値です。
左の図の場合は、j = 40の場合ですから、出席番号1から40までが対象範囲でbnは40ということになります。
       For j = 40 To 2 Step -1
         max = 0
         For k = 1 To j
           If a(i, k - 1, 0) > max Then
             max = a(i, k - 1, 0)
             bn = k
           End If
         Next
         For k = 0 To 6
           w = a(i, bn - 1, k)
           a(i, bn - 1, k) = a(i, j - 1, k)
           a(i, j - 1, k) = w
         Next
         For k = 0 To 12
           w1 = DataGridView1(k, i * 47 + bn + 1).Value
           DataGridView1(k, i * 47 + bn + 1).Value = DataGridView1(k, i * 47 + j + 1).Value
           DataGridView1(k, i * 47 + j + 1).Value = w1
         Next
       Next
でやっていることは、対象範囲の最大の出席番号を求め、
         For k = 0 To 6
           w = a(i, bn - 1, k)
           a(i, bn - 1, k) = a(i, j - 1, k)
           a(i, j - 1, k) = w
         Next
         For k = 0 To 12
           w1 = DataGridView1(k, i * 47 + bn + 1).Value
           DataGridView1(k, i * 47 + bn + 1).Value = DataGridView1(k, i * 47 + j + 1).Value
           DataGridView1(k, i * 47 + j + 1).Value = w1
         Next
によって対象範囲の一番下の行とすべてのデータを交換しているのです。
jは40→39→38→・・・→2と下がっていきますから、最初は40人の中で一番出席番号の大きいもの(つまり40番)のデータがすべて一番下の行のデータと交換されます。
次は39人の中で一番出席番号の大きい39番が対象範囲(39人中)の一番下、すなわち40人中の下から2番目の行とすべてのデータが交換されます。
以下、
38人の中で一番出席番号の大きい38番が対象範囲(38人中)の一番下、すなわち40人中の下から3番目の行とすべてのデータが交換されます、
37人の中で一番出席番号の大きい37番が対象範囲(37人中)の一番下、すなわち40人中の下から4番目の行とすべてのデータが交換されます、
36人の中で一番出席番号の大きい36番が対象範囲(36人中)の一番下、すなわち40人中の下から5番目の行とすべてのデータが交換されます、
             ・
             ・
             ・
2人の中で一番出席番号の大きい2番が対象範囲(2人中)の一番下、すなわち40人中の下から39番目の行とすべてのデータが交換されます、
と繰り返されて出席番号順に整理し直されるのです。

さて、課題です。
f11以前についても、分割できるものは分割してみましょう。

第2話へ 第4話へ

006

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

数学研究室に戻る