今回は、「C言語/様々な処理を取りまとめてユーザー定義関数を作る方法」についての説明です。
1.初めに
これまでの説明では、文字を表示するprintf、数字の変数を定義するintやdouble、条件分岐のif、繰り返し処理を行うforなど、様々な関数について説明してきました。
これらの関数は、『○○と入力すれば△△を実現できる』という具合に元々C言語で用意されている関数です。
このような元々用意されている関数とは別に、ユーザーが自分で関数を作ることが可能です。
ということで、今回はユーザー定義関数の作り方についてまとめていきます。
2.ユーザー定義関数の作り方
では、早速ユーザー定義関数の作成例について見ていきましょう。
#include<stdio.h>
double ave(double x, double y) {
double z = (x + y) / 2.0;
return z;
}
void main() {
double a;
a = ave(1.1, 8.9);
printf(“a = %f”, a);
}

このプログラムでは、平均値を求める関数を作ってみました。
ユーザー定義関数は、4~7行目に記述してあります。
【void main() {}】と記述すると、その中括弧内に記述した他の関数が実行されるという仕組みになっています。
これまでの説明では当たり前のように【void main() {}】の中括弧の中に全てのプログラムを組み込んでいましたが、これが通じるのは短めのプログラムまでです。
プログラムがある程度複雑になってくると、【void main() {}】に全て収めるのは難しくなります。
なので、今回はユーザー定義関数を外に出してみました。
こんな感じにしても問題無いのです。
関数を作るには、引数と戻り値というものが必要になります。
引数とは、4行目における【double x】及び【double y】のことです。
このユーザー定義関数は、最終的にはxとyを使ったaveという関数になります。
aveは平均の[average]から取りました。
つまり、aveという関数は、変数x及び変数yが変化すると、結果が変わるわけです。
このように、ユーザー定義関数に影響を与える変数が引数です。
y=2xという一次関数があったとして、x=1だとy=2、x=2だとy=4に変化するでしょう?
この関係をユーザー定義関数に置き換えて考えると、yがユーザー定義関数で、xが引数だということです。
ユーザー定義関数は、引数を用いて何らかの処理を行って定義します。
その処理の値を返すのが戻り値です。
言葉では説明しづらいんですよね。
5行目に【double z = (x + y) / 2.0;】と記述していますが、ここではzという変数が「(変数x + 変数y) / 2.0」であると定義しています。
ここで定義したzという変数は、6行目で【return z;】という処理をされています。
この処理により、zがaveに等しくなります。
このことを“処理の値を返す”と言ったのです。
つまり、ここで言う変数zが戻り値です。
戻り値であるzはdoubleで実数だと指定されているので、ユーザー定義関数であるaveもdoubleにしてあるのです。
こうしてユーザー定義関数aveが作られるのです。
ユーザー定義関数の使い方
こうしてユーザー定義関数を作ったら、次は実際に関数として使っていきます。
使い方はデフォルトで用意されているprintfなどの関数と同じです。
【void main() {}】の中括弧の中に普通にaveという関数を組み込んでいくだけです。
10行目で実数aを定義し、11行目で【a = ave(1.1, 8.9);】と記述しています。
ユーザー定義関数aveの引数は、実数xと実数yでした。
11行目の記述は、実数xを1.1、実数yを8.9に当て嵌めたものとなります。
要するに、【ave(x, y);】となるように入力するだけなのです。
何故そうなっているのかというと、4行目でユーザー定義関数aveの形態を指定しているからです。
4行目を改めて見ると、【double ave(double x, double y)】となっていますね?
この形式と一致するように11行目を記述しているのです。
そうすることにより、実数x及び実数yに代入する値を指定できるわけです。
そうして実数x=1.1、実数y=8.9になるので、z = (1.1 + 8.9) / 2 = 5.0となり、この戻り値の値がaveという関数により得られるわけです。
後はprintfでaの値を出力するように指定してあるだけです。
なので、プログラムを実行すると実数で5と表示されます。

ユーザー定義関数の動きを確認する(ステップイン)
ユーザー定義関数はmainの外に記述するので、プログラムが長く複雑になってきてしまうとどこに記述したユーザー定義関数なのかがよくわからなくなってしまいます。
そんな時は、デバッグのステップインを使うと簡単に割り出すことが可能です。
試しに11行目にブレークポイントを設けてデバッグを起動してみます。

ユーザー定義関数はmainの中に含まれているわけではないので最初は実行されず、9行目からプログラムは実行されます。
この時点では実数aが定義されただけなので、aの値はよくわからないことになっていますね。
ここでステップオーバーをすると、12行目に移動してしまいます。

上図がステップオーバーをした結果ですが、aveが実行されてaの値が5になっています。
つまり、ユーザー定義関数の処理を実行した後の状態まで飛んでしまうんです。
このように、普通にステップオーバーをしているだけでは、どこのユーザー定義関数が実行されたのかわからなくなってしまうのです。
今はプログラムが短くユーザー定義関数がaveしかないから気にする必要は無いですけどね。
そこで登場するのがステップインです。
ステップインは、ステップオーバーの左隣にあります。
丸に矢印が向かっているヤツですね。

このステップインを11行目のブレークポイントで実行すると、11行目で呼び出しているユーザー定義関数のところまで移動してくれます。

この状態でステップオーバーをすると、5行目に移動します。
その際に4行目が実行されるので、xとyの値が確定します。

ここでもう一度ステップオーバーをすると、5行目が実行されてzの計算結果が確定します。

そして、もう一度ステップオーバーをすると戻り値がaveに反映されるというわけです。
こうしてユーザー定義関数を実行した後にステップオーバーをすると、ユーザー定義関数の処理が終了し、11行目に戻ります。
このように、ユーザー定義関数の処理の動きを確認することが可能です。
また、ステップインしてユーザー定義関数の途中で確認を終わらせたくなった場合は、ステップアウトを押しましょう。
ステップオーバーの右隣にある丸から矢印が出ていくヤツです。

ちなみに、最初のブレークポイントの状態(図2)では「aveが返されました」なんて表示されていませんでした。
この過程ではステップインでユーザー定義関数の処理を実行してきたので、ここに差異が生じているのです。
この結果を手っ取り早く確認したい場合は、該当する箇所でステップイン後に即ステップアウトしましょう。
ユーザー定義関数をmainの外に出す利点
ユーザー定義関数をmainの外に出しても問題無く動くことがわかっていますが、このmainの外に出すということに利点が存在します。
それは、何度でもユーザー定義関数を使用できることです。
試しに、プログラムをちょっと書き足してみます。
#include<stdio.h>
double ave(double x, double y) {
double z = (x + y) / 2.0;
return z;
}
void main() {
double a, b, c = 2.0;
a = ave(1.1, 8.9);
b = ave(a, c);
printf(“a = %f\n”, a);
printf(“b = %f\n”, b);
}

新たに変数b及びcを定義し、cに関しては2.0に初期化をしました。
このプログラムを実行すると、以下のようになります。

12行目でもう1回関数aveが実行され、a(5.0)とc(2.0)の平均値としてb(3.5)が出力されていますね。
このように、ユーザー定義関数は一度定義してしまえば何度でも使用可能なので、うまく使いこなせばプログラムの記述をより単純にすることが可能です。
同じ処理をさせる記述をする手間を無くしたり、タイピングミスを防ぐことに繋がるのです。
以上、「C言語/様々な処理を取りまとめてユーザー定義関数を作る方法」についての説明でした。