C言語は関数からできています。Cのプログラムを作成するというのは,この関数を作成することなのです。実際にこれまでみなさんはmainという名前の関数を作ってきました。ここでは,他の関数を作ってmainや他の関数から使用してみたいと思います.
例えば,n! つまり n*(n-1)*(n-2)*…*2*1 を求める関数をfactriaと名づけ,この関数を作成することを考えましょう.この関数は,整数値nを入力パラメータとして与えると,整数n!を結果として返すという形にします.この関数を定義するプログラムは例えば次のように書けます.
1 int factria(int n) 2 { 3 int val,k; 4 5 val=1; 6 for(k=n; k>1; k--) val=val*k; 7 return val; 8 }
最初の番号は説明のための番号です.
前のプログラムの1行目に示すように,関数を定義するときにはまず関数名と関数名の前にその戻り値(この場合は関数名はfactriaで戻り値はintつまり整数)を指定し,関数名に続けて括弧内に入力パラメータ列を指定します.この例では入力パラメータは整数型の変数が1つであり,この関数内ではnという変数名で参照されます.
この行に続けて,この関数の中身を中括弧("{","}")で挟んで記述します.これまでに書いてきたmain関数の記述の方法とまったく同じです.注意する点としては,関数の中で利用する変数(この例では整数型の変数val,k)は,その関数の中で宣言して使用しなければならず,また関数の中で宣言した変数はその関数以外では参照できないということです.たとえ他の関数(例えばmain)で同じ名前の変数を宣言して使用したとしても,この関数の変数とはまったく違うものとして扱われます.具体的には違う箱が用意され,別々の値を持つことになるのです.
この例では,変数valにn!の値を計算して求めています.そして最後に7行目でこの関数を呼んだ元の関数にvalの値を戻り値として戻し,この関数の実行を終了します.このreturn文は後ろに戻り値を書き,関数の処理を終えることを示しています.
この関数を使って,例えば1〜7までの階乗の値を表示するプログラムは次のようになります.
#include <stdio.h> /* 関数のプロトタイプ宣言*/ int factria(int n); int main(void) { int k; for(k=1; k<=7; k++) printf("%d\n",factria(k)); } int factria(int n) { int val,k; val=1; for(k=n; k>1; k--) val=val*k; return val; }
なお,return文は関数の最後の行にしか書けないということはなく,関数を終了させたい任意の場所に書くことができます.また,2つ以上のreturn文が一つの関数の中に存在してもかまいません.例えばある条件に当てはまるかどうかを判定し,当てはまるなら戻り値を1,当てはまらなければ戻り値を0とする関数を考えるとき,次のような関数の形が考えられます.
int 関数名(入力パラメータ) { if(条件判定) return 1; else return 0; }
上のプログラムでは関数main内で,入力パラメータ値を1から7まで変化させながら関数factriaを呼んでいます.このとき,mainの中では変数kを使っていますが,このkの値と関数factria内の変数kの値とはまったく独立しています.この結果,関数factriaから戻ってきたときには,kの値は関数factriaを呼び出す前の値を保っています.
関数の定義はANSI標準規格に従って書いてあります.この規格ではmainの関数の前にプロトタイプ宣言をしてプログラムの中でどんな関数を使うか、関数の一覧を書きます.これは,コンパイラがプログラムを最初から読んでいくときに,mainの中で関数factriaを呼ぶことを発見するわけですが,この時点ではコンパイラはこの関数がどんな入力パラメータを持ち,戻り値の型が何であるのかを知らないため,ちょっと混乱します.この混乱を防ぐためのものです.
この章で考えてきた n! を計算する factria という関数は変数 n を与えて n*(n-1)*(n-2)*…*2*1 を計算しましたが。これを n*(n-1)! (n と n-1 の階乗の積)と考えることができます。すると、階乗の計算は関数 factria で計算できましたのでこの関数を利用することができます。すると、n! を計算する次のような関数を書くことができます。
#include <stdio.h> /* 関数のプロトタイプ宣言*/ int rfactria(int n); int main(void) { int k; for(k=1; k<=7; k++) printf("%d\n",rfactria(k)); } int rfactria(int n) { if (n > 0) return n * rfactria(n-1); else return 1; }
このように関数の中から自分自身の関数の呼び出しを含むことを再帰といい、再帰を用いたプログラムを再帰プログラムといいます。