工学部 6 7 8 9 10 組 ( 奇数学籍番号 ) 担当 : 長谷川英之 情報処理演習 第 9 回 2010 年 12 月 2 日 1
今回のメインテーマ : 関数呼び出し main 関数以外に所望の処理を行う関数 ( サブルーチン ) を定義して, その関数を main 関数の中で呼び出して仕事をさせること. これも重要な概念です. 頑張って理解して下さい. 2
#include <stdio.h> int sumdata(int a,int b) int n; n=a+b; return(n); main() int a,b,c; 関数呼び出しを使用した例プログラムh09.c printf( Input two integers. n ); scanf( %d %d,&a,&b); c=sumdata(a,b); printf( result=%d n,c); 3
プログラムh09.c #include <stdio.h> int sumdata(int a,int b) int n; n=a+b; return(n); main() int a,b,c; 関数呼び出しを使用した例 main 関数以外に sumdata という関数を定義 計算結果 n を返す. 関数 sumdata は int 型の関数と定義したため, 返す値 n も int 型である必要がある. printf( Input two integers. n ); scanf( %d %d,&a,&b); c=sumdata(a,b); 関数 sumdataに変数 a, bの値を渡して printf( result=%d n,c); 所望の処理を行い,sumdataが返した値をint 型変数 cに代入. 4
C 言語のプログラムでは,main 関数は必須であるが,main 以外に所望の処理を行うための関数を定義することができる. 定義方法はmain 関数と同様だが, int sumdata(int a,int b) のように, 関数の型は, 返される処理結果の型 ( 前ページの場合は2つの int 型変数の和をint 型として返す ) と一致している必要がある. 関数 sumdataの定義部分の説明 int sumdata(int a,int b) 関数 関数 sumdata が呼び出されたときに渡されるデータの型を定義. この例の場合,2 つの int 型のデータが受け渡される. int n; n=a+b; return(n); c=sumdata(a,b); sumdata は int 型関数として定義したため,int 型のデータを返す (return) 必要がある.int 型変数 n を返すようにすることで, 関数 sumdata に所望の処理 ( 加算 ) を行わせることができる. 変数 a も int 型なので,return(a); とすることも可能だが, その場合は a の内容をそのまま返すだけ. 関数 sumdata の呼び出し部分の説明 関数 sumdataを呼び出し,int 型変数 aとbの内容を引き渡す. sumdataの実行結果 ( 返されたint 型の値 ) をint 型変数 cに代入. 5
関数呼び出しを知ったことによって分かること 組み込み関数 c=sumdata(a,b); の書き方で思い出すのは, z=pow(x,y); や y=sin(x); などの使い方だと思います.pow や sin はいずれも float 型の関数で, 呼び出されたときに引き渡される変数が float 型変数 x,y です. これらの関数は, コンパイル時に lm というオプションを付けることで使えるようになります. つまり,-lm オプションは, 自分で作成した main 関数に pow,sin 関数をくっつけるということを意味しています.pow や sin などのようにもともと組み込まれている関数を, 組み込み関数と言います. 自分で作成する関数には, これら組み込み関数とは異なる名前を付ける必要があります ( この例の場合は sumdata). 配列と関数の書式配列を使う場合は a[i] のように中括弧 [ ] を使います.a( ) と書いてしまうと,a という関数を呼び出すことになってしまいます. 書き方が似ているので注意して下さい. 6
関数呼び出しによる組合せの計算 ( 教科書 P. 56 の必要最小 ) プログラムh09-2.c #include <stdio.h> long factorial(int x) int i; long f; 計算内容については次ページ参照 i=0; f=1; while(i<x) ++i; f=f*i; return(f); 教科書にある if と exit(1) のセットは,n と r に関する誤入力を避けるためのもの. オペレータが誤入力に注意すれば無くとも動作はする. main() int n,r; long ncr; main で呼び出されて返した値は long 型変数 ncr に代入されるため, 関数 factorial は long 型で定義. 引き渡される数 ( 引数 int x) は,main 関数にあるとおり n,r,n-r であるため int 型である. scanf( %d %d,&n,&r); ncr=factorial(n)/(factorial(r)*factorial(n-r)); printf( n=%d, r=%d, ncr=%ld n,n,r,ncr); factorial(n) は n! を返すので, この行は n!/(r! (n-r)!) を示す. 7
関数 factorial の計算内容 (n!) factorial が main 中で呼び出されたときの引数の値が x に引き渡される. 例えば,main 中で factorial(n) と呼び出した場合は,x の値は n となる. x=3の場合 iの値 fの値 i=0; f=1; while(i<x) ++i; f=f*i; 1. i と f の値をそれぞれ 0 と 1 に設定 2. i<x である限り, ++i; f=f*i; を繰り返す. 0 1 while ループ開始 1 1 2 2 3 6 i=x となり i<x を満たさないため while ループ終了 return(f) で返される f の値は 6 8
誤入力を避けるための処理部分の説明 ( 教科書の例 ) if(scanf( %d %d,&n,&r)!=2) scanf も組み込み関数なので, 返り値がある.scanf は読み込んだ値の 個数 を返すことになっている. 入力した値の数が 2 でないときは,2 以外の値を返すので, きちんと 2 つの値が入力されたかどうか判断できる. printf( Input 2 integers n ); exit(1); プログラムを終了させる.exit(0); は正常終了, exit(1); は異常終了を示す. この場合は,2 つの整数が入力されない場合 (!=2) なので異常終了させる. 9
変数の有効範囲の説明のプログラム ( 教科書 P. 60 の類似 ) プログラムh09-3.c #include <stdio.h> int a,b; int func(int x) int m; m=2; a=4; return(m*x); main() int m; m=5; a=2; b=func(a); printf( b = %d n,b); このプログラムで言いたいこと局所変数と大域変数 局所変数従来のように関数の 内で定義された変数 ( 左の例では関数 main と func の中の変数 m) その関数の中でのみ有効 大域変数関数の の外で定義された変数 ( 左の例では変数 a と b) ソースプログラムに含まれる関数全てで共通に使用される. 10
変数の有効範囲の説明のプログラム ( 教科書 P. 60 の類似 ) プログラムh09-3.c #include <stdio.h> int a,b; 大域変数はこのように関数の外で定義 int func(int x) int m; m=2; a=4; return(m*x); main() int m; 同じ文字 m を使用して 2 回変数定義がなされているが, それぞれ main と func の中でのみしか有効でないため, 重複して定義したことにはならない ( 局所変数 ). m=5; a=2; b=func(a); printf( b = %d n,b); 11
変数の有効範囲の説明のプログラム ( 教科書 P. 60 の類似 ) プログラムh09-3.c #include <stdio.h> int a,b; int func(int x) int m; m=2; a=4; return(m*x); main() int m; 変数 m の値を 5 に設定 ここで関数 func が呼び出されるので, func 中の変数 m は 2 にセットされるが, main 中の m の値は変わらず 5 である. m=5; a=2; b=func(a); printf( b = %d n,b); 関数 main 中で変数 m の内容を表示してみると, 相変わらず値は 5 であるはず. それに対し,b は a=2 と関数 func 中の m=2 の積であるから 4 になる. 12
これまでと異なる用法 return(m*x); これまで, int m,f; f=m*x; return(f); としていたものと同じ意味. 13
再帰的関数呼び出しによる組合せの計算 ( 教科書 p. 62 の必要最小 ) プログラムh09-4.c #include <stdio.h> long factorial(int x) printf( called: x=%2d n,x); if(x==0) return(1); else return(x*factorial(x-1)); 動作の説明は次ページ main() int n,r; long ncr; scanf( %d %d,&n,&r); ncr=factorial(n)/(factorial(r)*factorial(n-r)); printf( n=%d, r=%d, ncr=%ld n,n,r,ncr); 14
前ページの再帰的呼び出しの説明 例えば,n=3のときにfactorial(n) が呼び出されると次のような動作をする. 3*factorial(2) factorial(2)=2*factorial(1) なので 3*2*factorial(1) factorial(1)=1*factorial(0) なので 3*2*1*factorial(0) factorial(0)=1 なので 3*2*1*1 long factorial(int x) printf( called: x=%2d n,x); if(x==0) return(1); else return(x*factorial(x-1)); 漸化式の処理などに有用ですが, 使うには十分習熟することが必要でしょう. まず本資料 7 ページの使い方ができれば良いと思います. 15
課題 S9-20101202 float 型変数 x,y と int 型変数 a を引数とし,a が 0,1,2,3 のとき x+y,x-y,x*y,x/y をそれぞれ計算する関 calc を関数 main 中で呼び出すプログラムを作成せよ. 変数 x,y,a は main 中でキーボードで入力するようにすればよい. ソースプログラム中では calc を main より上に書いて下さい. 16