I 2008 0703 2008 0710 2008 711 http

  • Slides: 73
Download presentation
プログラミング論 I 2008年 07月03日 2008年 07月10日 2008年 7月11日 関数,再帰 http: //www. ns. kogakuin. ac.

プログラミング論 I 2008年 07月03日 2008年 07月10日 2008年 7月11日 関数,再帰 http: //www. ns. kogakuin. ac. jp/~ct 13140/Prog. 2008/ 1

FAQ: #defineとは? • 文字列を定義して,それ以降置換する. #define MAX 10 void main(){ int i=MAX; printf("%dn", i); }

FAQ: #defineとは? • 文字列を定義して,それ以降置換する. #define MAX 10 void main(){ int i=MAX; printf("%dn", i); } #define MAX 2*5 void main(){ int i=10/MAX; printf("%dn", i); } #define MAX (2*5) void main(){ int i=10/MAX; printf("%dn", i); } 置換 void main(){ int i=10/2*5; printf("%dn", i); } 置換 void main(){ int i=10/(2*5); printf("%dn", i); } 10/2*5は, 25です. 左から順に 計算 2

見やすい例 #include <stdio. h> void main(){ int i, j; for(i=0; i<10; i++){ for(j=0; j<10;

見やすい例 #include <stdio. h> void main(){ int i, j; for(i=0; i<10; i++){ for(j=0; j<10; j++){ if( (i + j) % 10 == 0 ){ printf("***n"); } else { printf("%d %dn", i, j); } } 4

関数の概要 2/3 1 #include <stdio. h> 2 void main(){ この 3行まとめて, 3 printf("Hello, ");

関数の概要 2/3 1 #include <stdio. h> 2 void main(){ この 3行まとめて, 3 printf("Hello, "); 1個のグループに 4 printf("World"); したい. 5 printf("!!!!n"); 6 printf("------n"); 7 printf("Hello, "); 8 printf("World"); 9 printf("!!!!n"); 10 printf("######n"); 11 printf("Hello, "); Hello, World!!!! 12 printf("World"); 実 ------13 printf("!!!!n"); 行 結 Hello, World!!!! 14 } 果 ###### Hello, World!!!! 9

関数の動作 1/2 ① 3 void print. HW(){ ④ 4 printf("Hello, "); 5 printf("World"); 6

関数の動作 1/2 ① 3 void print. HW(){ ④ 4 printf("Hello, "); 5 printf("World"); 6 printf("!!!!n"); 7⑤} 9 void main(){ ③ ② 10 print. HW(); ⑥ 11 printf("------n"); 12 print. HW(); 13 printf("######n"); 14 print. HW(); 15 } 11

関数の動作 2/2 3 void print. HW(){ ⑨ 4 printf("Hello, "); 5 printf("World"); 6 printf("!!!!n");

関数の動作 2/2 3 void print. HW(){ ⑨ 4 printf("Hello, "); 5 printf("World"); 6 printf("!!!!n"); 7⑩} 9 void main(){ 10 print. HW(); ⑦ printf("------n"); 11 ⑧ 12 print. HW(); ⑪ 13 printf("######n"); 14 print. HW(); 15 } 12

1 2 3 4 5 6 7 8 9 10 11 12 13 14

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #include <stdio. h> void sankaku(){ printf("*n"); printf("***n"); printf("****n"); } void gyaku_sankaku(){ printf("****n"); printf("**n"); printf("*n"); } void main(){ sankaku(); gyaku_sankaku(); } 関数の作り方 (例) この 1行で, sankaku() の 全てが一括して 実行される. 実 行 結 果 * ** **** *** ** *** **** *** ** * 15

解答 G-0 #include <stdio. h> void pr_hl_wld(){ printf("Hello, n"); printf("World!n"); } void main(){ pr_hl_wld();

解答 G-0 #include <stdio. h> void pr_hl_wld(){ printf("Hello, n"); printf("World!n"); } void main(){ pr_hl_wld(); } 17

関数の作り方 (引数の例) #include <stdio. h> void print. HW_n(int n){ int i; printf("Hello, World"); for(i=0;

関数の作り方 (引数の例) #include <stdio. h> void print. HW_n(int n){ int i; printf("Hello, World"); for(i=0; i<n; i++){ printf("!"); } /* n個の ! を表示 */ printf("n"); } void main(){ print. HW_n(4); print. HW_n(7); } for文を使う例 実行結果 Hello, World!!!!!!! 23

関数の作り方 (戻り値の例) 1 2 3 4 5 6 7 8 9 10 11 12

関数の作り方 (戻り値の例) 1 2 3 4 5 6 7 8 9 10 11 12 13 #include <stdio. h> int square(int n){ int sq; sq = n*n; printf("%d^2 = %dn", n, sq); return sq; } void main(){ int s; s = square(5); printf("square=%dn", s); } 実行結果 5^2 = 25 square=25 30

関数の作り方 (戻り値の例) 1 2 3 4 5 6 7 8 9 10 11 12

関数の作り方 (戻り値の例) 1 2 3 4 5 6 7 8 9 10 11 12 13 #include <stdio. h> double_square(double d){ 引数がdouble型1個なら, double sq; double型の値 1個を sq = d*d; 入れて,呼び出す. printf("%lf^2 = %lfn", d, sq); return sq; } 実行結果 1. 500000^2 = 2. 250000 void main(){ square=2. 250000 double s; s = double_square(1. 5); printf("square=%lfn", s); } 31

関数の作り方 (戻り値の例) 1 2 3 4 5 6 7 8 9 10 11 12

関数の作り方 (戻り値の例) 1 2 3 4 5 6 7 8 9 10 11 12 13 #include <stdio. h> double_square(double d){ 戻り値がdouble型なら, double sq; double型の値を sq = d*d; return する. printf("%lf^2 = %lfn", d, sq); return sq; } 実行結果 1. 500000^2 = 2. 250000 void main(){ square=2. 250000 double s; s = double_square(1. 5); printf("square=%lfn", s); } 32

関数の作り方 (戻り値の例) 1 2 3 4 5 6 7 8 9 10 11 12

関数の作り方 (戻り値の例) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include <stdio. h> int one(){ return 1; } int two(){ return 2; } int three(){ return 3; } i=1, void main(){ int i, j, k; i = one(); j = two(); k = three(); printf("i=%d, j=%d, k=%dn", i, j, k); } 実行結果 j=2, k=3 33

関数の作り方 (戻り値の例) 1 2 3 4 5 6 7 8 9 10 11 12

関数の作り方 (戻り値の例) 1 2 3 4 5 6 7 8 9 10 11 12 13 #include <stdio. h> int one(){ return 1; } int two(){ return 2; } int three(){ 実行結果 return 3; } i=1, j=2, k=3 void main(){ printf("i=%d, j=%d, k=%dn", one(), two(), three()); } printf()の中に直接記述してもOK. one() が"1",two()が"2"と思えば良い. 34

関数:複数のreturn • 関数内に return が 何個あってもよい. 実行結果 x=3 |x|=3 x=-4 |x|=4 1 2 3

関数:複数のreturn • 関数内に return が 何個あってもよい. 実行結果 x=3 |x|=3 x=-4 |x|=4 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include <stdio. h> int zettaichi(int n){ if( n<0 ){ return (-n); } else { return n; } } void main(){ int x, z; x = 3; z = zettaichi(x); printf("x=%d |x|=%dn", x, z); x = -4; z = zettaichi(x); printf("x=%d |x|=%dn", x, z); } 37

関数:return • return により, 関数は強制的に 終了する. 実行結果 AAAA BBBB 戻り値が無いときは, 単に return; と記述 1

関数:return • return により, 関数は強制的に 終了する. 実行結果 AAAA BBBB 戻り値が無いときは, 単に return; と記述 1 2 3 4 5 6 7 8 9 10 11 12 #include <stdio. h> void funct(){ printf("AAAAn"); printf("BBBBn"); return; printf("CCCCn"); } void main(){ funct(); } 38

関数の多段呼び出し 1/3 1 2 3 4 10 11 12 void func 0(){ printf("func 0

関数の多段呼び出し 1/3 1 2 3 4 10 11 12 void func 0(){ printf("func 0 start!n"); printf("func 0 end!n"); } void main(){ main() func 0(); } func 0() 実行結果 func 0() func 0 start! func 0 end! 41

関数の多段呼び出し 2/3 1 2 3 4 5 6 7 8 9 10 11 12

関数の多段呼び出し 2/3 1 2 3 4 5 6 7 8 9 10 11 12 void func 0(){ printf("func 0 } void func 1(){ printf("func 1 func 0(); printf("func 1 } void main(){ func 1(); } start!n"); end!n"); 実行結果 func 1 func 0 func 1 start! end! 42

1 2 3 4 5 6 7 8 9 10 11 12 13 14

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 int kaijoh(int x){ int r; if( x == 1 ){ return 1; } else { r = x * kaijoh(x-1); return r; } } void main(){ int n, k; n = 5; k = kaijoh( n ); printf("%d! = %dn", n, k); } 再帰:nの階乗 3/5 49

main() 再帰:nの階乗 4/5 kaijoh(3)は,3*kaijoh(2)は,2*kaijoh(1)は,1 kaijoh(1)=1 kaijoh(2)=2 kaijoh(2)は,2*1 kaijoh(2)=2 kaijoh(3)は,3*2 kaijoh(3)=6 n==1の時は, これ以上再帰呼 び出ししない. これがないと

main() 再帰:nの階乗 4/5 kaijoh(3)は,3*kaijoh(2)は,2*kaijoh(1)は,1 kaijoh(1)=1 kaijoh(2)=2 kaijoh(2)は,2*1 kaijoh(2)=2 kaijoh(3)は,3*2 kaijoh(3)=6 n==1の時は, これ以上再帰呼 び出ししない. これがないと 無限に続く 50

再帰:nの階乗 5/5 kaijoh( 4 =4* kaijoh( 3 =4* (3* kaijoh( 2 =4* (3* (2*

再帰:nの階乗 5/5 kaijoh( 4 =4* kaijoh( 3 =4* (3* kaijoh( 2 =4* (3* (2* kaijoh(1) =4* (3* (2* 1 =4* (3* ( 2 =4* ( 6 =24 ) ) ) 51

失敗例 1 2 3 4 5 6 7 8 9 10 11 int kaijoh(int

失敗例 1 2 3 4 5 6 7 8 9 10 11 int kaijoh(int x){ int r; r = x * kaijoh(x-1); return r; } void main(){ int n, k; n = 5; k = kaijoh( n ); printf("%d! = %dn", n, k); } kaijoh(5)を呼び出し ↓ kaijoh(4)を呼び出し ↓ kaijoh(3)を呼び出し ↓ kaijoh(2)を呼び出し ↓ kaijoh(1)を呼び出し ↓ kaijoh(0)を呼び出し ↓ kaijoh(-1)を呼び出し ↓ kaijoh(-2)を呼び出し ↓ kaijoh(-3)を呼び出し ↓ 無限に続く 52

ハノイの塔を解く関数 1 2 3 4 5 6 7 8 9 10 11 12 13

ハノイの塔を解く関数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include <stdio. h> void hanoi(int n, int pl. From, int pl. To, int pl. Other){ if( n == 1 ){ printf("move disk. %d ", n); printf("[%d -> %d]n", pl. From, pl. To); } else { hanoi(n-1, pl. From, pl. Other, pl. To); printf("move disk. %d ", n); printf("[%d -> %d]n", pl. From, pl. To); hanoi(n-1, pl. Other, pl. To, pl. From); } } void main(){ hanoi(5, 0, 1, 2); } 68

フィボナッチ数列 fibo(5) fibo(4) fibo(3) fibo(2) fibo(1) =1 fibo(2) fibo(0) fibo(1) =1 =1 fibo(3) fibo(1)

フィボナッチ数列 fibo(5) fibo(4) fibo(3) fibo(2) fibo(1) =1 fibo(2) fibo(0) fibo(1) =1 =1 fibo(3) fibo(1) =1 fibo(2) fibo(0) fibo(1) =1 =1 f(2)計算などの, 同じ処理を何度も fibo(0) fibo(1) 行っている. =1 =1 大変に非効率的 70

解答 G-2 #include <stdio. h> int fibo(int n){ if( n <= 1 ){ return

解答 G-2 #include <stdio. h> int fibo(int n){ if( n <= 1 ){ return 1; } else { return fibo(n-1)+fibo(n-2); } } void main(){ printf("%dn", fibo(7)); } これは例 73