第5回 http://www.fit.ac.jp/~matsuki/lecture.html プログラミングⅡ 第5回 http://www.fit.ac.jp/~matsuki/lecture.html
今日の内容 前回の課題説明 関数 関数の概要 関数の定義 関数の呼び出し 変数のスコープ 引数の受け渡し
関数の概要
関数の概要 預金をATMから引き出すときにすべきこと 複雑なコードを、何度も行うことは面倒。 一連の処理を、まとめて記述する (2)暗証番号を入力する。 (3)金額を指定する。 (4)お金を受け取る。 (5)お金と通帳を確認する。 複雑なコードを、何度も行うことは面倒。 一連の処理を、まとめて記述する ⇒ 関数(function)という機能がある。
関数の概要 これまで使った関数 関数とは,「一連の処理の集まり」 プログラマが,独自の関数を作ることができる main関数・printf関数・scanf関数 ⇒ C言語は関数で構成されている 関数とは,「一連の処理の集まり」 プログラマが,独自の関数を作ることができる
関数の概要 C言語で関数を利用するためには、次の手順が必要。 (1) 関数を作成する(関数を定義する) (1) 関数を作成する(関数を定義する) (2) 関数を利用する(関数を呼び出す)
関数の定義 戻り値の型 関数名(引数) { 文1; 文2; 文3; ・・・ return 式; } 関数名には、識別子を使う 処理をまとめえておく
関数の定義 /* buy関数の定義 */ void buy(void) { printf(“車を買いました。\n”); } 関数名 処理をまとめえておく voidとは、特定の型を持たないという意味
関数の概要 C言語で関数を利用するためには、次の手順が必要。 (1) 関数を作成する(関数を定義する) (1) 関数を作成する(関数を定義する) (2) 関数を利用する(関数を呼び出す)
関数の呼び出し 定義した関数を利用することを、 「関数の呼び出し」という。 関数を呼び出すには、関数名を記述する。 関数名(引数リスト); buy();
buy()関数の処理内容 buy()関数の処理が実行される 車を買いました #include <stdio.h> /*buy関数の定義 */ void buy(void) { printf(“車を買いました\n”); } /*main関数(buy関数の呼び出し)*/ main() buy(); buy()関数の処理内容 buy()関数の処理が実行される 車を買いました 実行画面
実行の流れ C言語は、「main関数」から処理が始まる。 ①関数を呼び出す ②関数内部の処理実行 ③呼び出し元に処理が戻る ② ③ ① #include <stdio.h> /*buy関数の定義 */ void buy(void) { printf(“車を買いました\n”); } /*main関数(buy関数の呼び出し)*/ main() buy(); ② ③ ①
関数の呼び出し 定義した関数は、何度でも呼び出すことができる buy(); 5回buy()関数が呼び出される
車を買いました もう一台車を購入します buy()関数を呼び出し もう一度、buy()関数を呼び出し 実行画面 #include <stdio.h> /*buy関数の定義 */ void buy(void) { printf(“車を買いました\n”); } /*main関数(buy関数の呼び出し)*/ main() buy(); printf(“もう一台車を購入します\n”); 車を買いました もう一台車を購入します buy()関数を呼び出し もう一度、buy()関数を呼び出し
#include <stdio. h> /. buy関数の定義 #include <stdio.h> /*buy関数の定義 */ void buy(void) { printf(“車を買いました\n”); } /*main関数(buy関数の呼び出し)*/ main() buy(); printf(“もう一台車を購入します\n”); ② ⑥ ③ ① ④ ⑤ ⑦
#include <stdio. h> /. main関数(buy関数の呼び出し) #include <stdio.h> /*main関数(buy関数の呼び出し)*/ main() { printf(“車を買いました\n”); printf(“もう一台車を購入します\n”); } 関数を使うほど面倒な処理ではない
/*buy関数の定義*/ void buy(void) { printf(“通帳をATMに入れます\n”); printf(“暗証番号を入力します\n”); printf(“金額を指定します\n”); printf(“お金を受け取ります\n”); printf(“お金と通帳を確認します\n”); printf(“車を買いました\n”); } 複雑な処理もまとめられる この短い呼び出しで、上記の複雑な処理を行うことが可能! buy();
引数
引数を使って情報を「渡す」 呼び出し元から関数内に情報(値)を渡し、 その値に応じて、処理を行う。 関数に渡す値のことを、「引数」という その値に応じて、処理を行う。 関数に渡す値のことを、「引数」という 値段の情報を利用した処理 値(値段)を一緒に渡す 呼び出し 「車を買いました」と 表示 main関数 buy関数 呼び出し元に 戻る
x /*buy関数の定義*/ void buy(int x) { printf(“%d万円の車を買いました\n”, x ); } 20 x /*buy関数の定義*/ void buy(int x) { printf(“%d万円の車を買いました\n”, x ); } int型の引数を用意 引数を関数内で使う 20
20万円の車を買いました 50万円の車を買いました 仮引数 実引数として20を渡して呼び出し 実引数として50を渡して呼び出し 実引数 実行画面 #include <stdio.h> /*buy関数の定義 */ void buy( int x ) { printf(“%d万円の車を買いました\n”, x ); } /*main関数(buy関数の呼び出し)*/ main() buy( 20 ); buy( 50 ); 20万円の車を買いました 50万円の車を買いました 仮引数 実引数として20を渡して呼び出し 実引数として50を渡して呼び出し 実引数
実引数:関数を呼び出す際に渡す値 仮引数:関数の定義内で値を受け取る変数
複数の引数を持つ関数 複数の引数をカンマ(,)で区切って指定 実引数と仮引数の数が一致しておくこと
引数の数だけ「カンマ(,)」で区切って変数を用意する(2個の引数を持つ関数としている) #include <stdio.h> /*buy関数の定義 */ void buy( int x , int y ) { printf(“%d万円と%d万円の車を買いました\n”, x, y ); } /*main関数(buy関数の呼び出し)*/ main() int num1 = 20; int num2 = 50; buy( num1, num2 ); 2個の引数を渡す 仮引数 実引数 x ← num1の値 y ← num2の値
printf(“%d万円と%d万円の車を買いました\n”, x, y ); } 20 50 x y void buy( int x , int y ) { printf(“%d万円と%d万円の車を買いました\n”, x, y ); } 20 50 main() { buy( num1, num2 ); } 20 50 num1 num2
戻り値 関数の呼び出し元に、関数本体から特定の情報を返す main関数 buy関数 呼び出し 関数で処理 呼び出し元に 戻る ある値を呼び出し元に返す
関数の定義 戻り値の型 関数名(引数) { 文1; 文2; 文3; ・・・ return 式; } 戻り値の型を指定 式の値を呼び出し元に返す return文はどこに書いても良い。 return文が実行されると、呼び出し元に処理が戻る。
関数の定義 /*buy関数の定義*/ int buy(int x, int y) { int z; printf(“%d万円と%d万円の車を買いました\n”, x, y ); z = x + y; return z; } int型の値を返すものとしている この値を呼び出し元に返す
戻り値を返す 戻り値は利用しなくても良い 戻り値を、sumに格納 #include <stdio.h> /*buy関数の定義*/ int buy(int x, int y) { int z; printf(“%d万円と%d万円の車を買いました\n”, x, y ); z = x + y; return z; } /*main関(buy関数の呼び出し)*/ main() int num1, num2, sum; num1 = 20; num2 = 50; sum = buy( num1, num2 ); printf(“合計で%d万円です”, sum); 戻り値を返す 戻り値は利用しなくても良い 戻り値を、sumに格納
関数の定義 戻り値を持たない関数 戻り値の型にvoid(ヴォイド)と指定する void buy(int x) { printf(“%d万円の車を買いました\n”, x); return; } 戻り値を指定する必要はない(この場合,return文はなくてもOK)
変数とスコープ
変数の種類 ローカル変数: 関数のブロック(中括弧で挟まれた部分)内で宣言した変数 グローバル変数: 関数のブロック外で宣言した変数
変数のスコープ(有効範囲) ローカル変数:関数の中で定義した変数 変数yのスコープ 変数xのスコープ int func( ) { int y; … } main() int x; x = 3; y = 5; 変数yのスコープ 変数xのスコープ func()にあるyを 参照することはできない!
変数のスコープ(有効範囲) グローバル変数:関数の外で定義した変数 変数zのスコープ 変数yのスコープ 変数xのスコープ int z; //グローバル変数 int func( ... ) { int y; z = 2; } main() int x; z = 1; グローバル変数 変数yのスコープ ローカル変数 変数xのスコープ
グローバル変数yとzのスコープ ローカル変数zとxのスコープ ローカル変数xのスコープ グローバル変数と同じ名前の int y; int z; void myfunc(int a) { int x; x = a; y = a; z = a; } main() int x; x = 10; y = 10; z = 10; printf(“x, y, zの値は%d, %d, %d\n”,x, y, z); myfunc( 5 ); グローバル変数yとzのスコープ グローバル変数と同じ名前の ローカル変数があるときは, ローカル変数が優先される ローカル変数zとxのスコープ 同じ名前であっても, ローカル変数は,別の変数と見なす ローカル変数xのスコープ
変数の寿命 変数を宣言 ⇒ メモリが確保される 変数を宣言 ⇒ メモリが確保される 利用しない変数のためにメモリを確保することは、非効率 ⇒ 利用が終わった変数のメモリは解放する 変数には、寿命がある⇒記憶領域(メモリ)を確保しておく期間が決まっている。
変数の寿命 x x ローカル変数:関数内で宣言してから、その関数が終了するまで 関数の始まり 関数の終わり メモリの解放 変数の宣言 メモリの確保 ローカル 変数X x x
変数の寿命 x x グローバル変数:プログラム本体の処理が始まる前から、プログラムが終了するまで プログラムの始まり プログラムの終わり メモリの解放 グローバル 変数X メモリの確保 x x
変数の寿命 通常、ローカル変数の寿命は、宣言されてから、その関数が終わるまで staticというキーワード〈記憶クラス指定子)で変数を宣言すると、 グローバル変数と同じ寿命を持つことができる。 ⇒「静的寿命を持つローカル変数」という
ローカル変数bはインクリメントされていない #include <stdio.h> int a = 0; void func(void) { int b = 0; static int c = 0; printf(“a = %d, b = %d, c = %d\n”, a, b, c); a++; b++; } main() func(); func(); func(); ローカル変数bはインクリメントされていない 実行結果 a = 0, b = 0, c = 0 a = 1, b = 0, c = 1 a = 2, b = 0, c = 2
プロトタイプ宣言 関数の定義 関数の呼び出し 関数の呼び出し 関数の定義 プロトタイプ宣言: 関数のひな型を呼び出し前に宣言しておく
プロトタイプ宣言 int addnum(int, int); n = addnum(2, 3); 関数名 戻り値の型 第1引数の型 第2引数の型 プロトタイプ 宣言 int addnum(int, int); n = addnum(2, 3); int addnum(int a, int b) { … } 関数の 呼び出し 関数の定義
#include <stdio.h> void dispnum(int a) { printf(“引数の値は%d\n”, a); } main() int x = 10; dispnum( 5 ); dispnum( x );
#include <stdio.h> void dispnum(int a); main() { int x = 10; dispnum( 5 ); dispnum( x ); } void dispnum(int a) printf(“引数の値は%d\n”, a); プロトタイプ宣言