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