第7章 関数の作りかた リスト 2数の平均値を求めるプログラム #include <stdio.h> double ave(double x, double y); ー関数プロトタイプ int main(void) { double a, b, avdt; a = 11.11; b = 33.33; avdt = ave(a, b); ー関数ave()を使って平均を求める printf(“a=%df b=%f 平均=%f\n”, a, b, avdt); return 0; } double ave(doub le x, double y) ー関数ave()の本体 { double wk; ー関数ave()の中だけで一時的に使用する変数 wk = (x + y) / 2.0; return wk; } ー渡された2数x,yの平均を求めwkに代入する ーwkの値を戻り値にする 実行結果 a=11.110000 b=33.330000 平均=22.220000 図7-1 関数呼び出しの関係図 main()側 ave()側 a,b avdt=ave(a,b); 答え avdt = ave(a, b); 2数の平均 a,bの値をx,yに渡す double ave(double x, double y) { double wk; wk = (x + y) / 2.0; その和を計算する return wk; } 答えを返す リスト 複数rerurn文と処理打ち切りreturn文の例 #include <stdio.h> #include <math.h> /* for sqrt() */ double maxdt(double a, double b); void disp_sqrt(double n); 関数プロトタイプ int main(void) { double mx; mx = maxdt(11.22, 33.44); printf(“mx=%f\n”, mx); disp_sqrt(2.0); disp_sqrt(-5.0); return 0; } ー最大値を求める ー平方根を表示 ー負値の引数で呼ぶ /* 大きい値を返す */ double maxdt(double a, double b)ー戻りの値の型はdouble { if (a > b) どれかのreturn文に出会うと return a; 値を返し処理を終了する else return b; } /* nが正の値なら平方根を表示する */ void disp_sqrt(double n) ー戻りの値がないのでvoid型に する { if (n <= 0.0) return; ー処理打ち切りのreturn文 printf(“%f の平方根=%f\n”, n, sqrt(n)); } 実行結果 mx=33.440000 2.000000 の平方根=1.414214 ←disp_sqrt(-5.0)の対応表示はない リスト void型関数の記述例 #include <stdio.h> void putd(int a); { putd(123); ー関数プロトタイプ return 0; } void putd(int a) ー数値を出力するだけで戻り値のない関数 { printf(“%d\n”, a); } ーreturn文による値戻しがない リスト void型引数の記述例 #include <stdio.h> void opening(void); ー関数プロトタイプ int main(void) { opening(); ー関数呼出側ではvoidを記述する必要はない return 0; } void opening(void) ー引数のない関数を定義 { printf(“program start\n”); } 関数プロトタイプの簡単記述方法 #include <stdio.h> double maxdt(double a, double b); ここに持ってくる int main(void) { ・・・ } double maxdt(double a, double b) { ・・・ } 自作関数の先頭行に’;’を付けて ◎プロトタイプ宣言を省略する方法 #include <stdio.h> double maxdt(double a, double b);ーこのプロトタイプでmaxdt() の仕様が判明しているので int main(void) { double mx; mx = maxdt(11.22, 33.44); -この呼び出しは正しく処理 される ・・・ } double maxdt(double a, double b) -maxdt()関数の本体 { ・・・ } #include <stdio.h> double maxdt(double a, double b);ー関数定義の先頭行でmaxdt() の仕様が判明するので ・・・ } int main(void) { double mx; mx = maxdt(11.22, 33.44);ーこの呼び出しは正しく処理さ ・・・ れる } 関数プロトタイプを 書くスタイルが正当 7.3関数にデータを渡す方法 ◎数値を渡す 値による呼び出し(Call by value) リスト 関数呼び出し側 a = 11.11, b = 33.33, avdt = ave(a, b); リスト 関数定義側 double ave(double x, double y) { double wk; wk = (x + y) / 2.0; return wk; } 代入 呼び出し側の変数aの値 関数側の変数x 代入 呼び出し側の変数bの値 関数側の変数y a = 100; avdt = ave(a, 200); 図7-2 値による呼び出し処理 呼び出し側 関数側 avdt=ave(a, 200); a 100 200 double ave(double x, double y) aの値(100)をxに代入 数値200をyに代入 wkの値(150)を avdtに代入 avdt 150 x 100 y 200 wk=(x+y) /2.0 を計算 wk 150 ◎配列を渡す アドレスによる呼び出し リスト 配列を関数に渡す1 #include <stdio.h> void disp_ary(int nn[]); int main(void) { int dt[5] = {100, 200, 300, 400, 500}; disp_ary(dt); ー配列の先頭アドレスを渡す return 0; } void disp_ary(int nn[]) ー配列を仮引数にする { printf(“nn[0]=%d\n”, nn[0]);ー配列内容を表示する printf(“nn[4]=%d\n”, nn[4]); } 図7-3 アドレスによる配列私のメカニズム main関数側 disp_ary()関数側 disp_ary(dt);でdtの内容(アドレス)である10000をnnに代入す る dt 10000 dt[0] 100 dt[1] dt[2] 200 10000番地 10004番地 300 10008番地 dt[3] 400 10012番地 dt[4] 500 10016番地 nn 10000 メモリ内の同じ配列を指 す リスト 配列を関数に渡す2 #include <stdio.h> void disp_ary1(int nn[], int len); void disp_ary2(int nn[]); int main(void) { int aa[5] = {100, 200, 300, 400, 500}; int bb[6] = {111, 222, 333, 444, 555, -1};-終了マークー1 をにする disp_ary1(aa, 5); -配列の先頭アドレスと配列長を渡す disp_ary2(bb); ー配列の先頭アドレスを渡す return 0; } void disp_ary1(int nn[], int len) -lenは配列長情報 { int i; for (i=0; i<len; i++) { printf(“%d ”, nn[i]);ーnn[0]~nn[len-1]を表示 } printf(“\n”); ー最後に改行 } void disp_ary2(int nn[]) { int i = 0; ー終了マーク方式 while (nn[i] != -1) { ー-1でない間ループする printf(“%d ”, nn[i]); ー値を表示 ++i; } printf(“\n”); ー最後に改行 } ◎文字列を渡す ‘A’ ‘B’ ‘C’ ‘D’ ‘E’ 0 これが目印 になる リスト 文字列を関数に渡す #include <stdio.h> void strout(char ss[]); int main(void) { char st[] = “ABCDEF”; strout(st); strout”ABab12”); return 0; } ー文字配列を渡す ー直接文字列を渡す void strout(char ss[]) { int i; ー引数をchar[]にする printf(“ss=%s\n”, ss); ー文字列をそのまま出力する i = 0; while (ss[i]) { ーss[i]が’\0’でない間ループする printf(“%X ”, ss[i]);ーss[i]を16進数出力 ++i } printf(“\n”); ー最後に改行する } 表7-1 ローカル変数とグローバル変数 ローカル変数 関数内で宣言され、その関数内でのみ参照できる グローバル変数 関数外で宣言され、どの関数からでも参照できる リスト 文字列を関数に渡す #include <stdio.h> void func(void); int glb; int main(void) { int a; ー関数の外側でグローバル変数gldを宣言 ーmain()関数内で使用できるローカル変数aを 宣言 a = 10; ー自分のローカル変数に値設定 gld = 20; ーグローバル変数に値設定 printf(“main a=%d glb=%d\n”, a, glb);ー両方の値を表示 func(); ー関数を呼ぶ return 0; } void func(void) { int b; ーfunc()関数内で使用できるローカル変数bを宣言 b = 99; ー自分のローカル変数に値設定 printf(“func b=%d gld=%d\n”, b, gld);ー両方の値を表示 } gldはmain()関数で設定した値 変数の通用範囲 int glb; int main(void) { int a; ・・・ 変数aの通用範囲 } 変数glbの通用範囲 void func(void) { int b; ・・・ } 変数bの通用範囲 ◎ローカル変数は衝突しない リスト ローカル変数の機能を見る #include <stdio.h> void func(void); int main(void) { int a; ー変数aを宣言する a = 100; printf(“main a=%d\n”, a);ー変数aの値を表示する func(); ー1度関数func()を呼んで printf(“main a=%d\n”, a);ー再び変数aの値を表示する return 0; } void func(void) { int a; ーこちらでも変数aを宣言する a = 22222; ー独自に値を設定する printf(“func a=%d\n”, a); ー変数aの値を表示する } ◎ローカル変数が優先される リスト グローバル変数よりローカル変数が優先される例 #include <stdio.h> void func(void); int gg = 1234; ー初期設定ありグローバル変数 int main(void) { printf(“main gg=%d\n”, gg);ーグローバル変数の値を表示 func(); -関数を呼ぶ printf(“main gg=%d\n”, gg);ーグローバル変数をもう1度表示 return 0; } void func(void) { int gg; ー同名のローカル変数を用意するとグローバル 変数ggは操作できなくなる gg = 9999; ー自分の変数ggに値設定 printf(“func gg=%d\n”, gg);ー自分の変数ggの値を表示 } ◎グローバル変数と外部変数 (1)staticの付かないグローバル変数(外部結合グローバル変数) (2)staticの付いたグローバル変数(内部結合グローバル変数) auto記憶クラス指定子 プログラム実行中にメモリ上に確保されたり消去されたりす る一時的な変数で、関数の中だけで使用できる。 extern記憶クラス指定子 プログラム実行中に常にメモリ上の同じ場所に存在する恒 久的な変数で、どの関数からも使用できる。externがあると、 よそで設定されたグローバル変数を参照しろという指定にな る。 static記憶クラス指定子 プログラム実行中に常にメモリ上の同じ場所に存在する恒 久的な変数で、関数の中で使用する方法と、関数の外で使 用する方法がある。 変数の通用範囲 #include <stdio.h> void func(void); int gg = 1234; グローバル変数を記述 int main(void) { printf(“main gg=%d\n”, gg); func(); グローバル変数ggを使用 myprg2.cにある関数を呼ぶ return 0; } myprg2.cの内容 #include <stdio.h> extern int gg; void func(void) { printf(“func gg=%d\n”, gg); } よそで宣言されている グローバル変数ggを利用 可能にする、という宣言 myprg1.cのグローバル 変数ggを使用できるよう になる ◎static記憶クラス指定子 リスト static変数の使用例 #include <stdio.h> void max_auto(int n); void max_static(int n); int main(void) { max_auto( 40); max_auto(100); max_auto( 80); max_static( 40); max_static(100); max_static( 80); 3つの値でmax_auto()を呼ぶ 3つの値でmax_static()を呼ぶ return 0; } void max_auto(int n) { int max = 0; ー変数maxは自動変数 if (n > max) max = n; ー最大値を記憶 printf(“max_auto max=%d\n”, max); ーその値を出力 } void max_static(int n) { static int max = 0; ー変数maxは静的変数 if (n > max) max = n; ー最大値を記憶 printf(“max_static max=%d\n”, max); ーその値を出力 } 記憶クラスの使い分け法 (1)通常は →自動変数を使う。ただし”auto”は省略する (2)値を保持したいときは →静的変数を使う(staticを付ける) (3)共通に使用したいときは→グローバル変数を使う リスト 外部変数を使ったデータやりとりの例 #include <stdio.h> void wasa(void); int n1, n2, wa, sa; ーグローバル変数の宣言 int main(void) { n1 = 300; n2 = 100; wasa(); ー引数なしで関数コールする printf(“n1=%d n2=%d 和=%d 差=%d\n”, n1, n2, wa, sa); return 0; } void wasa(void) { wa = n1 + n2; wa = n1 - n2; } ーグローバル変数を使うので引数不要 ー戻り値もグローバル変数に入れる
© Copyright 2024 ExpyDoc