第8講 Functionプロシージャ
第4話 成績一覧表作成ソフトのプロシージャによる改良その2
前話問題解答例
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
For i = 0 To 2
For j = 1 To 40
DataGridView1(8, i * 47 + j + 1).Value = g61(i, j)
DataGridView1(9, i * 47 + j + 1).Value = g62(i, j)
Next
Next
End Sub
Function g61(ByVal p As Integer, ByVal q As Integer) As Integer
Dim max As Integer
max = 0
For i = 1 To 5
If a(p, q - 1, i) > max Then max = a(p, q - 1, i)
Next
Return max
End Function
Function g62(ByVal p As Integer, ByVal q As Integer) As Integer
Dim min As Integer
min = 100
For i = 1 To 5
If a(p, q - 1, i) < min Then min = a(p, q - 1, i)
Next
Return min
End Function
'各学期合否・講評の算出・表示
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
For i = 0 To 2
For j = 1 To 6
DataGridView1(j, i * 47 + 42).Value = g8(i, j)
DataGridView1(j, i * 47 + 43).Value = g8(i, j) / 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
Function g8(ByVal p As Integer, ByVal q As Integer) As Integer
Dim w As Integer
w = 0
For i = 1 To 40
w = w + a(p, i - 1, q)
Next
Return w
End Function
'各学期各教科の最高点・算出の算出・表示
Sub f9()
Dim i As Integer, j As Integer
For i = 0 To 2
For j = 1 To 6
DataGridView1(j, i * 47 + 44).Value = g91(i, j)
DataGridView1(j, i * 47 + 45).Value = g92(i, j)
Next
Next
End Sub
Function g91(ByVal p As Integer, ByVal q As Integer) As Integer
Dim max As Integer
max = 0
For i = 1 To 40
If a(p, i - 1, q) > max Then max = a(p, i - 1, q)
Next
Return max
End Function
Function g92(ByVal p As Integer, ByVal q As Integer) As Integer
Dim min As Integer
min = 0
For i = 1 To 40
If a(p, i - 1, q) < min Then min = a(p, i - 1, q)
Next
Return min
End Function
'各学期の並び替え
Sub f10()
Dim i As Integer, j As Integer
For i = 0 To 2
For j = 40 To 2 Step -1
h10(i, j, g10(i, j))
Next
Next
End Sub
Function g10(ByVal p As Integer, ByVal q As Integer) As Integer
Dim min, bn, i, w As Integer
min = 500
For i = 1 To q
If a(p, i - 1, 6) < min Then
min = a(p, i - 1, 6)
bn = i
End If
Next
Return bn
End Function
Sub h10(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
'各学期順位付け
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
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
End Class
Funcitonプロシージャを利用できそうなところだけ、Functionプロシージャとして独立させました。
例えば、
'各学期各教科の最高点・算出の算出・表示
Sub f9()
Dim i As Integer, j As Integer
For i = 0 To 2
For j = 1 To 6
DataGridView1(j, i * 47 + 44).Value = g91(i, j)
DataGridView1(j, i * 47 + 45).Value = g92(i, j)
Next
Next
End Sub
Function g91(ByVal p As Integer, ByVal q As Integer) As Integer
Dim max As Integer
max = 0
For i = 1 To 40
If a(p, i - 1, q) > max Then max = a(p, i - 1, q)
Next
Return max
End Function
Function g92(ByVal p As Integer, ByVal q As Integer) As Integer
Dim min As Integer
min = 0
For i = 1 To 40
If a(p, i - 1, q) < min Then min = a(p, i - 1, q)
Next
Return min
End Function
をご覧になればおわかりのように、g91とg92がそれぞれ最高点と最低点を算出するFunctionプロシージャということで、
Sub f9()
Dim i As Integer, j As Integer
For i = 0 To 2
For j = 1 To 6
DataGridView1(j, i * 47 + 44).Value = g91(i, j) '最高点算出
DataGridView1(j, i * 47 + 45).Value = g92(i, j) '最低点算出
Next
Next
End Sub
の部分が
'各学期各教科の最高点・算出の算出・表示
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
と比べてすっきりしました。3次元ループが2次元ループに落ちているからです。
各プロシージャが次元を分担することによって、
各プロシージャ内の次元を落とすことが出来るのです。
2次元と1次元にしましたがもちろんすべて1次元にすることも出来ます。
では皆さん、'各学期各教科の最高点・算出の算出・表示をすべて1次元にすることに挑戦して下さい。
解答例は、30行下。
解答例
'各学期各教科の最高点・算出の算出・表示
Sub f9()
Dim i As Integer
For i = 0 To 2
g90(i)
Next
End Sub
Sub g90(ByVal p As Integer)
For i = 1 To 6
DataGridView1(i, p * 47 + 44).Value = g91(p, i)
DataGridView1(i, p * 47 + 45).Value = g92(p, i)
Next
End Sub
Function g91(ByVal p As Integer, ByVal q As Integer) As Integer
Dim max As Integer
max = 0
For i = 1 To 40
If a(p, i - 1, q) > max Then max = a(p, i - 1, q)
Next
Return max
End Function
Function g92(ByVal p As Integer, ByVal q As Integer) As Integer
Dim min As Integer
min = 0
For i = 1 To 40
If a(p, i - 1, q) < min Then min = a(p, i - 1, q)
Next
Return min
End Function
こうすると
Sub f9()
Dim i As Integer
For i = 0 To 2
g90(i)
Next
End Sub
の仕組みがはっきりします。
iは0,1,2と動きますが、これはそれぞれ1学期、2学期、3学期に対応します。
つまり、1次元ループの役割は各学期処理であると、
一目でわかりやすくなりました。
'各学期各教科の最高点・算出の算出・表示
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
と比較すればわかりやすさは断然違います。
では、
Sub g90(ByVal p As Integer)
For i = 1 To 6
DataGridView1(i, p * 47 + 44).Value = g91(p, i)
DataGridView1(i, p * 47 + 45).Value = g92(p, i)
Next
End Sub
の役割は何でしょうか。iの0,1,2,3,4,5,7はそれぞれ国語、社会、数学、理科、合計、平均に対応しています。
つまり、ここの1次元ループの役割は各教科などの処理です。
そして、
Function g91(ByVal p As Integer, ByVal q As Integer) As Integer
Dim max As Integer
max = 0
For i = 1 To 40
If a(p, i - 1, q) > max Then max = a(p, i - 1, q)
Next
Return max
End Function
が最高点の算出
Function g92(ByVal p As Integer, ByVal q As Integer) As Integer
Dim min As Integer
min = 0
For i = 1 To 40
If a(p, i - 1, q) < min Then min = a(p, i - 1, q)
Next
Return min
End Function
が最低点の算出を分担していたことがわかります。iの1から40は出席番号に相当します。
では、第8講の最後の課題を出してこの話を閉めます。
実行画面をご覧になればおわかりのように、成績一覧表作成ソフトは各学期の処理は行っていますが、
年間処理を行っていません。
そこで年間処理を行っていだますが、Private Sub Button1_Clickは、
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
'見出し表示やデータ作成などの基本処理
g()
'各学期処理
s()
'年間処理
t()
End Sub
3つのプロシージャを組み立てものとして
gにはf1()からf4()までの基本処理を、sには各学期処理(すなわちf5()からf12()までの処理)を、tには年間処理をさせてください。
もちろん、年間処理の中には、各学期のデータを加えてデータを書き込むだけでなく、
各学期合計値・平均値の算出・表示、各学期各生徒の最高点・最低点の算出・表示など各学期で処理した同内容の各処理を行わなければなりません。
個々の処理は、SubプロシージャまたはFunctionプロシージャに担当させてください。
尚、tとsの内容は新たに作るのではなく、既存の部品(プロシージャ)を利用して下さい。
tについても、出来るだけ既存の部品(プロシージャ)を再利用して下さい。
既存の部品を再利用できる、これが構造化プログラミングの大きな利点の1つです。
部品の再利用といえば、実はf12()は、f10()を少し改造しておけば再利用できるので、不要なのです。
これについても考えてください。
第3話へ 第5話へ
VC++講義第1部へ
vb講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座
数学研究室に戻る