160 likes | 287 Views
関数の定義. 前回の復習. 配列・配列の初期化 while, for, do 文 break, continue, goto 文. printf() は便利だなー. printf(“Hello, world !<br>”); は printf() がどのように動いているかは知らないが、画面に希望の文字列が表示 される。このような表現の際、 printf を 関数名 といい、 () の中の ”Hello, world<br>” を 実引数 という。また、 printf(“Hello, world<br>”) を関数を評価する、または、 printf に
E N D
前回の復習 • 配列・配列の初期化 • while, for, do 文 • break, continue, goto文
printf()は便利だなー printf(“Hello, world !\n”); はprintf()がどのように動いているかは知らないが、画面に希望の文字列が表示 される。このような表現の際、printfを関数名といい、()の中の”Hello, world\n”を 実引数という。また、printf(“Hello, world\n”)を関数を評価する、または、printfに “Hello, world\n”を引数に与えて関数を呼び出すという。関数の評価は 関数名(実引数) の形をとる ひとまとまりの処理を内部の動作を見えない形で実現するものを関数という
C言語での関数の定義 関数の型 関数名(仮引数1の型,{仮引数2の型,…}); /*プロトタイプ宣言*/ 関数の型 関数名(仮引数1の型 仮引数名1,{仮引数2の型 仮引数名2,…}) { 変数の宣言 文 return(計算結果); } void 関数名(仮引数1の型 仮引数名1,{仮引数2の型 仮引数名2,…}) { 変数の宣言 文 {return;} } 省略可.ある場合は計算結果があってはならない!
関数定義の例 実数を2つ取って、その和を計算する関数 #include <stdio.h> double dadd(double, double); int main(void) { dou ble a,b,c; scanf(“%lf%lf”,&a,&b); c=dadd(a,b); printf(“%f+%f=%f\n”,a,b,c); } double dadd(double x, double y) { double z; z =x + y; return(z); } プロトタイプ宣言のメリット 実引数と仮引数の型の不一致の検出 → バグの発見 実引数の自動型変換
仮引数への実引数の引き渡し double dadd(double x=2, double y=3) { double z; z =x + y; return(5); } #include <stdio.h> double dadd(double, double); int main(void) { dou ble a,b,c; scanf(“%lf%lf”,&a,&b); c=5; printf(“%f+%f=%f\n”,a,b,c); } #include <stdio.h> double dadd(double, double); int main(void) { dou ble a,b,c; scanf(“%lf%lf”,&a,&b); c=dadd(a,b); printf(“%f+%f=%f\n”,a,b,c); } double dadd(double x=2, double y=3) { double z; z =x + y; return(z); } dadd(2,3)
関数導入の理由 • プログラムの構造を見やすくし、ソースファイルをコンパクトに • トップダウン的プログラムの作成関数毎にプログラムを分割して作製(引数と返り値の属性と名前さえ分かっていればプログラムの作成は可能) • 関数内での処理の隠蔽(ぺい) • 関数のライブラリ化による共有化のメリット
例 #include <stdio.h> #define N 100 #define M 100 int main(void) { double data1[N], data2[M]; ReadData(data1, N); ReadData(data2, M); } void ReadData(double data[], int n) { int i; for(i=0;i<n;i++) scanf("%lf", &data[i]); } int i; for(i=0;i<N;i++) scanf("%lf",&data1[i]); for(i=0;i<M;i++) scanf("%lf",&data2[i]);
変数の有効範囲:自動変数と静的変数(1) [自動変数] 自動変数はブロック内で定義された変数で、そのブロック{}内だけで有効で、プログラムがそのブロックの外に出ると自動的に消滅する。初期化はプログラムが{}に入る毎にされる。 int main(void) { int a; a = 1; { int a: a = 2; } printf("a = %d\n",a); } { int b; a = 2; } { int a; a = b; } ○ ×
変数の有効範囲:自動変数と静的変数(2) [静的変数] 変数宣言の型の前にstaticを付ける プログラムの実行の前に一回だけ初期化され、プログラムの実行中は常に 定義されている変数 [大域変数] 全ての{}の外で宣言されている変数は基本的に全てのプログラム内で使用可能。 staticを付けるとそのファイル内だけで有効になる!
static変数の応用 void f1() { static int count=0; count++; ... } void f2() { static int count=0; count++; .... } 関数の呼び出された回数を関数内に記憶する
関数の再帰呼び出し(1) • 定義している関数内で、その関数を呼び出す • 演算の再帰的定義に類似→ 効率的なプログラミング→ 再帰的に定義されるデータ構造処理が簡潔
関数の再帰呼び出し(2) Int factorial(int n) { if(n==0) return(1); else return(n*factorial(n-1)); }
factrial(3)の実行例 int ans; ans = 6; int ans; ans = factorial(3); factorial(n←1) { return(1*1); } factorial(n←3) { return(3*factrial(2)); } factorial(n←2) { return(2*1); } factorial(n←2) { return(2*factrial(1)); } factorial(n←1) { return(1*factrial(0)); } factorial(n←3) { return(3*2); } factorial(n←0); { return(1); }
main()も関数だった int main(void) {…} もmainという関数の定義だった 引数はなし、戻り値は整数 Cのプログラムでは最初必ずmainという関数が実行される