Visual Basic 6.0 初級講座 |
第17回 関数2
今までも小出しにしてきたのですが、今回は改めて関数を説明します。数学の関数も私は大好きでしたがVBの関数もキュートです。みなさんも関数と仲良くつきあってください。
私の感覚でははっきりいって関数なしでプログラムなどできません。極論すればプログラムとは関数を作ることとも言えます。
1.関数を作る
関数の基本については以前に説明しましたから今回は自分で関数を作ってみましょう。n角形の内角の和を求める関数を作ってみます。
念のために説明しておくと、3角形の3つの角の角度をすべて合計するとどんな形の三角形でも必ず180度になります。このことを「3角形の内角の和は180度である」と言います。同様に四角形の4つの角を合計すると360度になるので「4角形の内角の和は360度」です。このようにn角形の内角の和は決まっています。n角形の内角の和を求めるには次の式を使います。
( n - 2 ) × 180
たとえば、3角形の内角の和をこの式を使って求めるにはnに3を代入して (3−2)×180 を計算すればよいわけです。
では、n角形の内角の和を返す関数を作ってみます。最初に関数の名前を決めましょう。ここでは私が勝手にInner関数(インナー)と名付けます。
完成したInner関数はたとえば次のようになります。
MsgBox Inner(4)
この例ではメッセージボックスには4角形の内角の和である 360 が表示されます。
さて、このInner関数を具体的にプログラムすると次のようになります。
Private Function Inner ( Number As Integer ) As
Integer
End Function |
1行目は関数の形式を宣言しています。Privateキーワードは「この関数は外部から使用できない」という意味です。分からなければPrivateと書いておけば大丈夫です。次のFunction(ファンクション)は「関数」と言う意味です。関数を作るときにはこのFunctionキーワードが必ず必要です。次のInnerは作る関数の名前です。その次のかっこの中はこの関数の引数です。この場合は引数はInteger型(整数型)です。なお、引数にNumberと言う名前を付けました。ここで付けた名前で引数を参照することができます。最後のAs Integerはこの関数の戻り値はInteger型(整数型)であるという意味になります。
関数を作るときには1行目ですべての形式を宣言するのでまずはこの1行目の書き方を覚えてください。1行目を打ち込んでEnterキーなどを押すと自動的に3行目のEnd Functionが表示されます。関数の内容はこのPrivate FunctionからEnd Functionの間に記述することになります。
この関数は単純なので内容はたったの1行です。引数から2を引いた数に180をかければよいのですから2行目の意味はすぐに分かるでしょう。Inner = となっているのでこの式の値がそのまま戻り値になると言うわけです。
以上であなたのプログラムにはn角形の内角の和を算出する関数が追加されました。いつでも Inner(3)のようにしてこの関数を使用することができます。まったくVBに最初から備わっている関数と変わらない使用感ですね。いろいろ便利な関数を自作してプログラムを強化するというのはどうでしょう?
練習問題
1.一辺の長さがnである正方形の面積を求める Square関数を作りなさい。
資料:世界の常識ですが、1辺nの正方形の面積は次の式で求められます。
n × n
2.n角形の対角線の数を求める Diagonal関数を作りなさい。
資料:数学上では次の式でn角形の対角線の数を求められます。
n × (n−1) ÷ 2 − n
2.複数個の引数
もう少し複雑な関数も作ってみましょう。平均を求めるAverage関数(アベレージ)関数です。3つの引数の平均を求めるようにプログラムしてみましょう。
さきほどとの大きな違いは引数が3つあることです。引数が複数個ある場合には引数の間を 、 で区切ります。完成したAverage関数は次のようになるでしょう。
Private Function Average(A As Double, B As Double, C
As Double) As Double
End Function |
今回は小数も扱う必要があるのでInteger型(整数型)ではなく、Double型(倍精度浮動小数点型)にしました。
これでMsgBox Average (2 , 5 , 8)とすると 5と表示されるのですがこの関数はあまり役に立ちません。というのも引数が3つだからです。平均を計算するときはもっとたくさんの数を計算することになるでしょう。
VBはこのような要望にも応えてくれます。引数の数があらかじめ決まっていない場合は関数の1行目にParamArrayキーワードを使います。たとえば次のように新しいAverage関数を記述します。
Private Function Average( ParamArray Numbers() As
Variant) As Double Dim K As Integer Dim Stock As Double Dim ArrayCount As Integer ArrayCount = UBound(Numbers()) For K = 0 To ArrayCount Stock = Stock + Numbers(K) Next K Average = Stock / (ArrayCount + 1) End Function |
いきなり長くなってしまいましたが、このAverage関数なら引数がいくつでも対応できますから実用性があります。
まず、1行目の引数に注目してください。ParamArray Numbers() As Variant となっています。これは引数がいくつあっても対応できる関数を作るときの決まり文句です。ParamArrayキーワードにより、引数はすべて配列Numbers()に格納されることになります。また本来Numbersのデータ型はDouble型とすべきですが、ParanArrayキーワードを伴う場合にはVariant型しか使用できません。
基本的には変更点はここだけのはずなのですが、いくつの引数が渡されたか分からないのでそれを判定する分プログラムが長くなっています。引数はすべて配列Numbers()に格納されていますから、Numbers()にいくつの数字が格納されているかを調べれば渡された引数の数が分かります。配列に含まれる要素(この場合は数)の個数を調べるには標準で装備されているUBound関数を使います。ただし、配列の一番最初はNumbers(0)なので、正確な個数はUbound関数で得られた値に1をたした物になります。
引数の数が分かれば、For Nextでループを回してすべての引数を合計します。最後は引数の数でそれをわっておしまいです。
ParamArrayは私の中では結構上等なキーワードです。使用方法はご理解いただけましたか?
練習問題
3.2つの引数のうち大きい方を返すMaxNumber関数を作りなさい。
この関数を利用して MsgBox MaxNumber ( 5 , 9 )とすると 9 が表示されるというわけです。
4.複数の引数の中からもっとも小さい数を返すMinimum関数を作りなさい。
3.機能的な関数
本来関数は戻り値が重要なはずなのですが、戻り値にたいした意味のない関数も作成できます。たとえば、次の関数はフォーム上に配置されているすべてのコントロールをVisibleプロパティを逆にします。つまり見えているコントロールを見えなくし、見えないコントロールを見えるようにします。いくつかコントロールを配置して試してみてください。
Private Function VisibleSwitch()
End Function |
まず、目に付くのが引数と戻り値の宣言がないことです。この関数は引数を1つもとらないということです。それに戻り値もありません。(正確には Empty値(エンプティ)と言う特殊な値を返しています)。
この関数が内部でやっているFor Each等はまだ説明していませんが今回はここは重要ではありません。要は戻り値が重要じゃない関数があるということです。この関数は戻り値のためにあるのではなくコントロールの表示を切り替えるためにあるのです。つまり戻り値ではなく「機能」が重要なのです。
このような機能的関数は結構たくさんありますので留意して下さい。
ところで、この関数の機能を呼び出すには普通の関数のようにします。たとえば M = VisibleSwith() とするとこの関数が発動します。戻り値を格納するMはどうでもいいです。この他次の章で説明している関数の呼び出し方も参照してください。
4.関数の呼び出し方
通常は関数は M = Function(Parameter) のように使用します。この例では関数の戻り値がMに格納されます。しかし、これ以外にも関数を呼び出す方法はあります。
代表的な物をあげましょう。戻り値を使用しない場合はCallステートメント(コール)を使用して次のように呼び出すこともできます。
Call Average (4 ,5 ,7)
この例では戻り値を格納していないので平均を取得できません。この用法では通常戻り値の重要ではない「機能的な関数」を呼び出します。
この方式を簡略化して次のように記述することもできます。
Average 4, 5, 7
Callステートメントを省略した形ですがこの場合は引数をかっこでくくりません。引数をかっこでくくるとエラーが発生します。この方式で引数のない関数を呼び出すと次のようになります。
VisibleSwitch
しかし、これでは後で見たときにこの命令が何を意味しているかわかりにくいという欠点があります。そのためこの1行が関数の呼び出しであることを明確にするために常に引数を格納するか Callステートメントを使用することをおすすめします。
5.値渡し
機能的な関数を作ります。つまり戻り値は設定しません。関数の内容は2つの変数の値を入れ替えるという物です。関数の名前はSwap(スワップ)にします。この関数は次のような使い方ができる物とします。
X = 123
Y = 7
Call Swap(X , Y)
Print X '7と表示されます
Print Y '123と表示されます
関数の機能は単純なのでプログラムも楽です。次のようにすると良いでしょう。
Private Function Swap(A As Variant , B As Variant)
End Function |
実際この関数は目的の機能を備えています。
ここで言いたいことは「関数は渡された引数を変更することができる」と言う点です。このため関数の中でうかつに引数を変更すると自分でも気がつかないエラーの原因となってしまいます。
この引数を変更する機能をいろいろと活用するというのもおもしろそうですが、場合によっては引数を変更したくないときもあります。関数の1行目の引数の宣言の前にByValキーワード(バイバル)を使用すると関数の中で引数を変更しても実際の変数の値は変更できないようにすることができます。たとえば、次のように使用します。
'悪い例 Private Function Swap2(ByVal A As Variant , ByVal B As Variant)
End Function |
しかし、この関数は引数を変更できないので結局何もしない関数になってしまいました。まぁ中にはByValを必要とする場合もあると言うことです。たとえばAPIと呼ばれる種類の関数の多くはByValを必要とします。
なお、今まで通りByValをつけない場合は実はByRefをつけた場合と同じです。そこで明示的にByValじゃないことを示したい場合にはByRefを使用します。ByRefを使用した引数の渡し方を「参照渡し」、BuValを使用した引数の渡し方を「値渡し」と言います。
6.省略可能引数
最後に説明しもらした点を簡単に説明します。Optinal(オプショナル)キーワードを使うと引数を省略可能にできます。OptinalはByValと同じ位置に記述します。また、この引数が省略された場合の規定値を設定することもできます。次の関数はその例です。
Private Function YearEx (WestYear As Integer,
Optional Flag As Integer = 0 )
End Function |
この関数は西暦を平成に変換します。たとえばYearEx(2001) = 13 となります。ただし、イスラム教とのためにイスラム歴に変換する機能もあります。イスラム歴に変換するには第2引数に1を指定します。たとえば、YearEx(2001,1)=1379です。第2引数に0を指定すると明示的に平成に変換します。
これ以上のくどい説明は必要ないでしょう。なお、Optinalキーワードを使うとその後ろのすべての引数にもOptinalキーワードを使用しなければなりません。ようするにとちゅうの引数だけを省略可能にするわけには行かないのです。
7.結び
みなさんも便利な関数をつくったら是非紹介してください。インターネット上にも関数を公開している人を時折見かけます。
あと一言言っておきますが、最近はVBのずいぶん便利になって自分で関数を作る必要性はどんどん低くなっています。機能的な関数はまだまだ自作の領域なのですが、戻り値を重視するタイプの関数はほとんど自作する必要がありませんね。前に大学入試のセンター試験で任意の位で四捨五入する関数が出題されたことがあります。みなさんはどのような方法で任意の位で四捨五入していますか?