復習 前回の関数のまとめ(1) 関数はmain()関数または他の関数から呼び出されて実行される. 関数を呼び出す側の実引数の値が関数内の仮引数(変数)に コピーされる 関数内で求めた値はreturn文によって関数値として呼び出し側に戻される. #include <stdio.h> 関数の定義 float menseki(float a, float b) { return (a * b / 2); } a, b: 仮引数 仮引数もローカル変数 →関数内でのみ有効 int main(void) { float x, y, kekka; printf("底辺は?"); scanf(" %f ", &x); printf("高さは?"); scanf(" %f ", &y); 関数の呼び出し } kekka = menseki(x, y); printf("面積は%fです.¥n", kekka); x,y:実引数 復習 前回の関数のまとめ(2) 関数はプログラム上の部品(機能単位)である. 関数内の変数はお互いに独立である(干渉しない). #include <stdio.h> float menseki(float a, float b) { float s; s = a * b / 2; return s; } menseki()関数 同じ変数名a,bでも,関数 が違うと,別の変数と見な される main()関数 int main(void) { float a, b, kekka; printf("底辺は?"); scanf(" %f ", &a); printf("高さは?"); scanf(" %f ", &b); kekka = menseki(); printf("面積は%fです.¥n", kekka); } 関数定義におけるreturn 文 float menseki(float a, float b) { float s; s = a * b / 2; return s; } int func(int x, int y) { if (x*y % 2 == 0) { return 1; } } return文を実行し ない場合があるの でダメ. 復習 float menseki(float a, float b) { return a * b / 2; } return文の文法 return 式; int func(int x, int y) { if (x*y % 2 == 0) return文を実行すると関 数を終了する.式の値 { を関数値として戻す. return 1; } else { return文は複数あって return 0; もOK.但し,どのような } 場合でも必ずその一つ } を実行すること. return文で戻る値を返り値 あるいは戻り値と呼ぶ 関数の戻り値 float menseki(float a, float b) { float s; s = a * b / 2; return s; } int main(void) { float x, y; printf("底辺は?"); scanf("%f", &x); printf("高さは?"); scanf("%f", &y); menseki(x, y); printf("計算はしたよ\n"); } menseki()関数の 戻り値が変数に代 入されていない! 質問 これはコンパイル エラーになるか? printf(・・・) scanf(・・・) main() これらは全て関数 但し,一般に戻り値は 利用されない 答え エラーにはならない. 関数値の戻り値は代入され なくてもかまわない. void キーワード 関数値を持たない(返さない)関数の定義 voidは戻 り値が無 いことを 宣言 void kansu(float a, float b) { 何も返さないので,return 式 ; .... とは書かない. return; return文の省略も可能! } int main(void) { int x; x = kansu(3, 4); printf("x=%d, %d", x, kansu(2,5)); } void 宣言された 関数の関数値を 利用しようとする とエラー 引数としてvoidと書くと, 引数が無いことを宣言 int func(void) { return 5; } int main(void) { printf("値は%d", func()); } main()関数 関数値は int型 (関数値を戻す) int func(void) { return 5; } voidなので 引数は無い int main(void) { printf("値は%d", func()); } void 宣言されていない関数 ではreturn文は省略できな いはず!! main()関数は特殊な関数である 関数の戻り値のまとめ 戻り値がある関数でも,必要がなければ,呼び出し側でそれを使 わなくても(代入しなくても)かまわない. 戻り値が無い関数を定義する場合,あらかじめvoid宣言をする. この場合,return文で値を戻さない.また,return文自体も省略可. void宣言された関数で戻り値を利用しようとするとエラーになる. void mul10(int a) { a = a * 10; return; } int main(void) { int x = 12; mul10(x); printf("x = %d", x); } x = 12 ?? 引数を10倍す る関数 疑問 なぜこのmul10()関数は 意図どおりに働かないか? 引数の値渡し int main(void) { int x = 12; mul10(x); printf("x = %d", x); } 引数を10倍 する関数 void mul10(int a) { a = a * 10; return; 原則 引数のコピーが関数 } に渡され,呼び出し側の 変数は変化しない. ⇒値渡し(call by value) x = 12 main()関数 変数 12 関数呼び出し mul10()関数 引数の値のコピー x 局所変数 ローカル変数 120 12 a return文実行 例外 ポインタ引数,配列引数 ⇒参照渡し(call by reference) 配列を引数とする関数 #include n個のデータの合計を求め る関数 <stdio.h> int sum(int data[], int n) { int s = 0, i; for (i = 0; i < n; i++) { s = s + data[i]; } return s; } int main(void) { int i, aa[50], s; データの個数がn個 (≠配列宣言の要素数) 理由:配列宣言時の要素数と有効なデータ数は 同じではないので! データを入れる配列 要素数を空欄にする.→data[n]× data[0]× // 配列aa[]に30個のデータを入力する ・・・ //省略 s = sum(aa,30); printf(“データの合計は%d\n”,s); aa[0]からaa[29]に30個の値 を代入しておく 関数呼び出し 配列名のみ書く.[ ]は不要 有効なデータの個数は30個 } 配列引数は自動的に参照渡しだが,この例では配列要素の値は変化させていない 配列引数(参照渡し)を用いた関数 #include <stdio.h> void mul10(int data[], int n) { int i; for (i = 0; i < n; i++) { data[i] = data[i]*10; } } n個のデータの値を10倍す る関数 関数宣言と引数の書き方 は同じ 配列引数は参照渡しである ため,呼び出し側の配列の 値が変化する! int main(void) { int i, aa[50], s; // 配列aa[]に30個のデータを入力する ・・・ //省略 関数の呼び出し方法も同じ mul10(aa,30); printf(“データを全て10倍すると”); ・・・ //データの表示(省略) } 参照渡しにより配列要素の値を変化させる例 配列aa[0]~aa[29]の値は 全て10倍されている. 引数のまとめ 値渡し(基本) 関数を呼び出した側の実引数の値が変化しない. 配列引数とポインタ引数を除く他の全ての引数 参照渡し(例外) 関数を呼び出した側の実引数の値が変化する. 以下の二つのみ. 配列引数 ポインタ引数(2年で学習) 関数のデバッグ [A] ツールバーでデバッグを始める手順 (1) ツールボタンで右クリックして,デバッグを選ぶ (2) デバッグツールバーからボタンを選ぶ (3) (1)ステップオーバー (2) ステップイン (3) デバッグの中止 (2) (1) 次の行を実行 次の行を実行 デバッグをやめる [B] メニューでデバッグを始める手順 デバッグメニューで,ステップオーバーを選ぶ ステップインは関 数内部に入って 1行づつ実行す る
© Copyright 2024 ExpyDoc