サイトマップ / C言語講座>出入り口>総目次>目次:再帰>関数の再帰呼び出し
[2次元ポインタ配列]←このソース→[10進数を16進表示]
今日は階乗を求める関数を例にして、再帰呼び出しについて学びます。再帰呼び出し(Recursive call)とは、関数の中で自分自身と少し異なる自分を呼び出すことです。全く同じ自分を呼び出すことではありません。無限ループになってしまいます。
再帰呼び出しの関数のコードを記述するのは、慣れないと難しいのですが、再帰に向いているルーチンならば、短くて強力なソースプログラムを書くことができます。
まず、ある整数の階乗を返す関数を再帰を使わないで作ります。
nの値が大きくなるにつれて、nの階乗の値は急速に増加します。そこで戻り値は long型の整数とします。階乗を英語では" Factorial "というので、nの階乗を求める関数の名前を下記のようにします。
long Factorial1(int n) ;
nが0か1の時
なので、上記の2行をそのままソースコードにすると、次のようになります。
if (n == 0)
return (1L);
else if (n == 1)
return (1L);
しかし、これは次に示すように、論理演算子(|| :論理和)を使えばもっと簡潔に記述できます。
if (n == 0 || n == 1)
return (1L);
では、nが3より大きい場合について考えます。ループを使えば良さそうです。long型の変数pを宣言し、1Lに初期化しておく。ループの中で、もし、nが1より大きければ、pにnを掛け、nの値を1減少させる。
上記の文をそのままコードにすると、関数は次のようになります。
long Factorial1(int n)
{
long p = 1L;
if (n == 0 || n == 1)
return (1L);
else if (n > 1) {
for ( ; n > 0; n--)
p = p * n; // * 注
return (p);
}
}
* 注:pはlong型で、nはint型なので、
この掛け算はnがlong型に変換されてから行われる。
キャストの必要はない。
次に再帰版を作ります。
long Factorial2(int n);
Cでは、関数を呼び出す時、スタックに値を積みます。呼ばれた関数の側は積まれた値を利用します。これを値による呼び出し(Call by value)といいます。再帰版のソースを下記に示します。
// 階乗を求める(再帰版)
long Factorial2(int n)
{
if (n == 0 || n == 1) // n が 0 か 1 なら
return (1L); // 1 を返す
else // n に自分より 1 小さい自分を掛ける(これが再帰呼び出し)
return (n * Factorial2(n -1));
}
この関数を呼び出すと何が起こるか、次の説明をじっくり眺めて下さい。
Factorial2(n)の中に、n * Factorial2(n -1);と記述してあります。メインルーチンからFactorial2(n)が呼ばれると、次の一連の出来事が起こります。
Factorial2(1)が呼ばれると、順次スタックに積まれた値とのかけ算をしながら戻ります。 最後に、Factorial2(n)で、 n * Factorial2(n -1)の計算が行われ、 Factorial2(n)を呼び出したルーチンに戻ります。 その結果、階乗が求められます。
ソースプログラムの再帰版と非再帰版の長さを比べて下さい。再帰版では短くなったと思います。 */
#include <stdio.h>
long Factorial1(int n) ;
long Factorial2(int n) ;
void main(void);
/* 階乗を求める(非再帰版) */
long Factorial1(int n)
{
long p = 1L;
if (n == 0 || n == 1) /* nが0か1なら */
return (1L); /* 1を返す */
else if (n > 1) {
for ( ; n > 0; n--)
p = p * n;
return (p);
}
}
/* 階乗を求める(再帰版) */
long Factorial2(int n)
{
if (n == 0 || n == 1) /* nが0か1なら */
return (1L); /* 1を返す */
else /* nに自分より1小さい自分を掛ける */
return (n * Factorial2(n -1));
}
void main(void)
{
int n;
long f;
printf("整数を入力して下さい\t");
scanf("%d", &n);
f = Factorial1(n);
printf("Factorial1( ) = %ld\n", f);
f = Factorial2(n);
printf("Factorial2( ) = %ld\n", f);
}
|
[2次元ポインタ配列]←このソース→[10進数を16進表示]
/* (C) 2000- YFプロ. All Rights Reserved. */ 提供:C言語講座−それ自体コンパイルできる教材を使った講座です−