第7講 Subプロシージャ

第1話 Subプロシージャとは?

SubプロシージャとFunctionプロシージャはC言語で言うと関数です。
Subプロシージャは戻り値を持たない関数、Functionプロシージャは戻り値を持つ関数に対応します。
関数というと、ブルーな気分になってしまう方もいらっしゃるかもしれませんね。
『苦手だな。』と。
でも全然いりませんよ。
関数とは独立パーツのことです。
プラモデルでいえば、部品に相当します。
プラモデルの部品は、独立部品です。
独立とはどういうことでしょうか。
人間の内臓もいろいろなパーツももっています。
胃、腎臓、肝臓など。
しかし、これらのパーツは独立していません。
例えば、腎臓が悪くなると、将来的には肝臓などの他の臓器なども影響を受けます。
肝臓もやられると、やがてはいろいろな臓器が悪くなっていきます。
内臓を含む人間の中のいろいろなパーツは、
有機的に相互に複雑に関連しあっています。
だから、糖尿病が進行すると最悪失明します。
それに対して、プラモデルの方は、ある部品が壊れても他の部品には何の影響も与えません。
部品同士が、有機的に複雑に関連しあっているのではなく、単純結合をしているだけだからです。
それに対して、例えば脳細胞はシナプスを通して複雑に結びついています。
Webサイト同士の関係も蜘蛛の巣のように非常に複雑に絡み合っています。
プラモデルの部品は結びつきが簡単です。高々数カ所で繋がっているだけです。

もし、プログラムを構成するパーツが脳細胞やWebサイトのように複雑に絡み合っているとすれば、
理解が難しく、組むのも大変になってしまいます。
昔のBASICは、各パーツが独立していなくて、それぞれのパーツが脳細胞のシナプス結合のように複雑に関連しあっていました。
Go To文を通して、あちらこちらを行ったり来たりしていて、スパゲッティプログラムと呼ばれていました。
最大の問題点は、各パーツが独立していないので、
同じ変数名を使っていると知らないうちに他のパーツで値が書き換えられれしまう可能性がありました。
つまり、かつてのBASICでは、常にプログラムの全体を見ていないと、プログラムが組めなかったわけです。
そして、パーツの中にいくつも出口と入り口があって、プログラムを複雑なものにしていました。
これだともちろん何百人の人が分業して、プログラムを組むことは不可能だったわけです。

幸いにしてC言語の方は、最初から構造化プログラミングという考え方がしっかりしていました。
構造化プログラミングというは、独立パーツをプラモデルのように単純に結合させていくプログラミングです。
ポイントは、二つです。
一つは、各部品は完全に独立していてたとえ同じ変数名を使用していても、
他のパーツで書き換えられてしまう心配はありません。
そして、入り口と出口が原則一つであるというのが二つ目のポイントです。
結びつきを単純にするためです。
独立部品から全体を組み立てることを構造化プログラミングというのです。

BASICもVisual Basicになった現在、かつての欠点が改善されC言語に負けない構造化プログラミングができるようになっています。
さらに、BASIC時代のもう一つの欠点、インタプリタでコンパイラでないという問題も改善されていますので、
Visual Basicは、Visual C++に遜色しないものとなっています。
VC++はポインタなど初心者には難しい内容があり、敷居が高いので入門言語としてはVBの方が優れています。



具体例を作って説明していきましょう。第6講で作ったDo..Loop While文による2次元ループ開いてください。
もし、上書きなどでそのソフトがすでにない場合は、下のように新たにタイピングして下さい。
Public Class Form1

   Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
     '変数の宣言
     Dim a(4, 4) As Integer, b(4, 4) As Integer, i As Integer, j As Integer, w As String

     '自然行列の発生
     
     Do
       
       Do
         a(i, j) = i * 5 + j + 1
         j = j + 1  'これを忘れると永久ループになる
       Loop While j < 5
       i = i + 1
     Loop While i < 5

     '転置行列の発生
     
     Do
       
       Do
         b(j, i) = i * 5 + j + 1
         j = j + 1
       Loop While j < 5
       w = w & vbNewLine
       i = i + 1
     Loop While i < 5

     '自然行列の表示
     w = ""
     
     Do
       
       Do
         If a(i, j) < 10 Then w = w + "0" + a(i, j).ToString + " "
         If a(i, j) >= 10 Then w = w + a(i, j).ToString + " "
         j = j + 1
       Loop While j < 5
       w = w & vbNewLine
       i = i + 1
     Loop While i < 5
     Label1.Text = w

     '転置行列の表示
     w = ""
     
     Do
       
       Do
         If b(i, j) < 10 Then w = w + "0" + b(i, j).ToString + " "
         If b(i, j) >= 10 Then w = w + b(i, j).ToString + " "
         j = j + 1
       Loop While j < 5
       w = w & vbNewLine
       i = i + 1
    Loop While i < 5
    Label2.Text = w


    '自然行列と転置行列の和表示
    w = ""
    
    Do
      
      Do
        If a(i, j) + b(i, j) < 10 Then w = w + "0" + (a(i, j) + b(i, j)).ToString + " "
        If a(i, j) + b(i, j) >= 10 Then w = w + (a(i, j) + b(i, j)).ToString + " "
        j = j + 1
      Loop While j < 5
      w = w & vbNewLine
      i = i + 1
    Loop While i < 5
    Label3.Text = w

   End Sub
End Class

このプログラムコードは、長すぎて全体を見通すのが大変です。

そこで、枠で囲った部分を独立させます。
そして、それぞれのパーツ名を順にf1()、f2()、f3()、f4()、f5()とすると、
Public Class Form1

   Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
     '変数の宣言
     Dim a(4, 4) As Integer, b(4, 4) As Integer
     
     '自然行列の発生
     f1()

      '自然行列の表示
     f2()

      '転置行列の発生
     f3()

     '転置行列の表示
     f4()

     '自然行列と転置行列の和の計算と表示
     f5()

   End Sub

End Class
とかなり見通しのよいものになります。

各部品をプロシージャといいます。先に述べたようにプロシージャには2種類あります。SubプロシージャとFunctionプロシージャです。
実は、
   Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
     '変数の宣言
     Dim a(4, 4) As Integer, b(4, 4) As Integer
     
     '自然行列の発生
     f1()

      '自然行列の表示
     f2()

      '転置行列の発生
     f3()

     '転置行列の表示
     f4()

     '自然行列と転置行列の和の計算と表示
     f5()

   End Sub

もSubプロシージャのの一つです。ただし、これは独立部品5つf1()、f2()、f3()、f4()、f5()から組み立てたものになっています。
独立部品=Subプロシージャを作るには、

上図の矢印の行で
Sub f()
と打ち、エンターします。すると自動的に
Public Class Form1

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

   End Sub
End Class
となり、Subプロシージャができます。
Subプロシージャは、戻り値を持っていませんが
Functionプロシージャは戻り値を持ちます。
また、SubプロシージャもFunctionプロシージャも引数を持つこともあります。
Functionプロシージャが引数と戻り値を持つ場合が、数学の関数に対応します。
f(x)は、値xを渡され、値を加工して値を返すものだからです。

渡す値を引数(ひきすう)といいます。そして、返される値を戻り値といいます。

先の手順で
Public Class Form1

   Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
     '変数の宣言
     Dim a(4, 4) As Integer, b(4, 4) As Integer,i As Integer, j As Integer, w As String

     '自然行列の発生
     f1()

     '転置行列の発生
     f2()

     '自然行列の表示
     f3()
 
     '転置行列の表示
     f4()

     '自然行列と転置行列の和表示
     f5()

   End Sub

   Sub f1()
     '自然行列の発生
     i = 0
     Do
       j = 0
       Do
         a(i, j) = i * 5 + j + 1
         j = j + 1
       Loop While j < 5
       i = i + 1
     Loop While i < 5
   End Sub

   Sub f2()
     i = 0
     Do
       j = 0
       Do
         b(j, i) = i * 5 + j + 1
         j = j + 1
       Loop While j < 5
       w = w & vbNewLine
       i = i + 1
     Loop While i < 5
   End Sub

   Sub f3()
     w = ""
     i = 0
     Do
       j = 0
       Do
         If a(i, j) < 10 Then w = w + "0" + a(i, j).ToString + " "
         If a(i, j) >= 10 Then w = w + a(i, j).ToString + " "
         j = j + 1
       Loop While j < 5
       w = w & vbNewLine
       i = i + 1
     Loop While i < 5
     Label1.Text = w
   End Sub

   Sub f4()
     w = ""
     i = 0
     Do
       j = 0
       Do
         If b(i, j) < 10 Then w = w + "0" + b(i, j).ToString + " "
         If b(i, j) >= 10 Then w = w + b(i, j).ToString + " "
         j = j + 1
       Loop While j < 5
       w = w & vbNewLine
       i = i + 1
     Loop While i < 5
     Label2.Text = w
   End Sub

   Sub f5()
     w = ""
     i = 0
     Do
       j = 0
       Do
         If a(i, j) + b(i, j) < 10 Then w = w + "0" + (a(i, j) + b(i, j)).ToString + " "
         If a(i, j) + b(i, j) >= 10 Then w = w + (a(i, j) + b(i, j)).ToString + " "
         j = j + 1
       Loop While j < 5
       w = w & vbNewLine
       i = i + 1
     Loop While i < 5
     Label3.Text = w
   End Sub

End Class

これで一見良さそうなのですが、ビルドするとエラーしてしまいます。
実は、
Dim a(4, 4) As Integer, b(4, 4) As Integer,i As Integer, j As Integer, w As String
に問題があります。

(図のの部分に問題があるとVisual Basicが指摘しています。)
理由は、プロシージャの独立性です。
各変数は、プロシージャの中でのみ有効なのです。
したがって、i,j等は赤い枠の中では有効ですが、
その下では、有効ではありません。
したがって、i,j等は無宣言の変数と見られてしまいます。
プロシージャの中でのみ有効な変数をローカル変数といいます。
基本的にVisual Basicで出てくる変数は、ローカル変数なのです。
しかし、プログラム全体に有効な変数も用意されています。
それをグローバル変数といいます。
グローバル変数は、メモリを無駄遣いするので、基本的には使わないことが推奨されていますが、
初心者用の簡単なプログラムにおいては、グローバル変数を使っても全然問題ありません。
ただ、この講が進むとすべてローカル変数で対応できるようになります。

ローカル変数を宣言するには、Dim a(4, 4) As Integer, b(4, 4) As Integer,i As Integer, j As Integer, w As Stringについては
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Clickの前に行におけばグローバル変数になります。

Public Class Form1
   '変数の宣言
   Dim a(4, 4) As Integer, b(4, 4) As Integer,i As Integer, j As Integer, w As String
   Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
     
     '自然行列の発生
     f1()

     '転置行列の発生
     f2()

     '自然行列の表示
     f3()
 
     '転置行列の表示
     f4()

     '自然行列と転置行列の和表示
     f5()

   End Sub

   Sub f1()
     '自然行列の発生
     i = 0
     Do
       j = 0
       Do
         a(i, j) = i * 5 + j + 1
         j = j + 1
       Loop While j < 5
       i = i + 1
     Loop While i < 5
   End Sub

   Sub f2()
     i = 0
     Do
       j = 0
       Do
         b(j, i) = i * 5 + j + 1
         j = j + 1
       Loop While j < 5
       w = w & vbNewLine
       i = i + 1
     Loop While i < 5
   End Sub

   Sub f3()
     w = ""
     i = 0
     Do
       j = 0
       Do
         If a(i, j) < 10 Then w = w + "0" + a(i, j).ToString + " "
         If a(i, j) >= 10 Then w = w + a(i, j).ToString + " "
         j = j + 1
       Loop While j < 5
       w = w & vbNewLine
       i = i + 1
     Loop While i < 5
     Label1.Text = w
   End Sub

   Sub f4()
     w = ""
     i = 0
     Do
       j = 0
       Do
         If b(i, j) < 10 Then w = w + "0" + b(i, j).ToString + " "
         If b(i, j) >= 10 Then w = w + b(i, j).ToString + " "
         j = j + 1
       Loop While j < 5
       w = w & vbNewLine
       i = i + 1
     Loop While i < 5
     Label2.Text = w
   End Sub

   Sub f5()
     w = ""
     i = 0
     Do
       j = 0
       Do
         If a(i, j) + b(i, j) < 10 Then w = w + "0" + (a(i, j) + b(i, j)).ToString + " "
         If a(i, j) + b(i, j) >= 10 Then w = w + (a(i, j) + b(i, j)).ToString + " "
         j = j + 1
       Loop While j < 5
       w = w & vbNewLine
       i = i + 1
     Loop While i < 5
     Label3.Text = w
   End Sub

End Class
このようにすると、の記号がすべて消えて、ビルドに成功して

となります。
プロシージャの中でしか通用しないローカル変数は、不便なようですが、
これがプロシージャの独立性を保証するものになります。



第6講第6話へ 第2話へ

006

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

数学研究室に戻る