プログラミング演習I 2003年6月11日(第9回) 木村巌
今日やること 関数の続き 関数の再帰呼び出し 配列を引数とする関数 変数のスコープ、エクステント 大復習大会!質問コーナー!!
知識編:関数 引数として幾つかの値を取り、一定の処理をして、値を返す……関数 例: int main (int ac, char *av[]){} int型のac, char型のポインタの配列avを取り、int型の値を返す. 定義の仕方は前回の資料を見よ(教科書8章)
配列を引数とする関数 左の例だと、main()内のaの値は、foo()の呼出し後も変わらない 教科書8.2節 void foo(int a) { int a = 2; return; } int main (void) { int a = 1; foo(a); printf (“%d\n”, a); return 0;
配列を引数とする関数 void foo(int a[]) { a[0]= 2; return; } int main (void) { foo(a); printf (“%d\n”, a[0]); return 0; 左の例では、実際にa[0]が書き換えられる 配列を引数とすると、配列の0番目の成分の(メモリ上の)場所(ポインタ)が渡される foo()では、その場所に2を書き込んでいる
関数の再帰呼び出し 関数の中で、自分自身を呼び出すことが可能. これを「再帰呼び出し」、もしくは単に「再帰」という(recursive call, recursion) 例: 階乗の計算.n! = n * (n – 1)!そのもの long factorial (long n) { if (n == 1) return 1; else return n * factorial (n – 1); }
関数の再帰呼び出し 再帰呼び出しの別: 前者は、一種のgoto文とみなせる 最後に、その関数を呼び出しているだけ(真正な末尾再帰、proper tail recursion) 最後に、その関数呼び出しを含むある式を評価している 前者は、一種のgoto文とみなせる プログラミング言語によっては、真正な末尾再帰を実際にgoto文として取り扱うものもある 例:プログラミング言語Scheme
末尾再帰の例 unsigned long tmp = 1; unsigned long factorial_pr (unsigned long n, unsigned long t) { if (n == 1) return tmp; else { tmp *= n; return factorial_pr (n – 1, tmp); }
再帰の他の例 Fibonacci数列:f(0) = 0, f(1) = 1, f(n) = f(n - 1) + f(n – 2). long fib (long n) { if (n == 0) return 0; if (n == 1) return 1; return fib (n – 1) + fib (n – 2); }
再帰の他の例 再帰的なデータ構造の操作(リスト、ツリーなど) ある種のソート 後でやりましょう
変数のスコープ 変数にはスコープ(可視範囲、通用範囲)がある. ファイルスコープ 関数スコープ ブロックスコープ
ファイルスコープ すべての関数の外で宣言された変数は、そのファイル全体にわたって可視.ファイルスコープという. 複数の関数から可視.しかしファイルスコープの変数を使ってデータのやり取りをすべきではない(プログラムの見通しが悪くなる)
ファイルスコープ変数の例 #include <stdio.h> int a = 1; void foo (void) { return; } void bar (void) { a = 3; int main (void) { printf (“%d\n”, a); foo (); printf(“%d\n”, a); bar (); return 0; }
関数スコープ 関数スコープ:関数内で宣言された変数は、その関数の内部からのみ可視 他の関数に同じ変数名があっても、独立している
関数スコープの変数:例 int foo (void) { int a = 1; return a; } int bar (void) { int main (void) { printf (“%d, %d\n”, foo(), bar()); return 0; } /* 1, 2 と表示される */
ブロックスコープ 複合文(ブロック)の先頭で宣言された変数. その複合文の内部からのみ可視 同じ関数内でも、異なる複合文からは不可視
変数のエクステント 変数には、可視範囲(プログラムの字面上、どこから見えるか)のほかに、生存期間(エクステント)がある. プログラムの実行中、いつからいつまでその変数が有効か? Cでは、変数の記憶クラス(storage class)として指定する
auto変数 auto変数(自動変数)は、関数スコープ、ブロックスコープの変数のデフォルトの記憶クラス. その変数の可視範囲にプログラムの制御がわたった時点で有効になり、プログラムの制御がその変数の可視範囲から外れた時点で無効になる.
外部変数 ファイルスコープ変数のエクステントは、プログラムの実行期間と等しい. プログラムが実行される直前(main()に制御がわたる直前)に有効になり、main()からreturnした時点で無効になる
static変数 auto変数は、関数、もしくは複合文から制御が離れた時点で、無効化される 再び同じ関数、もしくは複合文に制御がわたると、前に保持された値が再び見える
まとめ 関数の再帰呼び出し 配列を引数とする関数 変数のスコープ、エクステント
教科書で既にやった範囲 テキストの内容でまだやってないのは、 それ以外(1~6章、8, 10章)は既に学んだ事項です.よく復習しておくこと! 文字列に関する箇所 コンソール入出力(7章) ポインタ 標準ライブラリ関数の大半 ファイル入出力の大半 それ以外(1~6章、8, 10章)は既に学んだ事項です.よく復習しておくこと!
レポート課題 今回はレポートなし 中間試験に備えてください. 試験がなくても備えてください.備えよ常に. おまけ;レポートがなくて退屈なあなたに スーパーコンピュータコンテスト2003予選問題 高校生向けのコンテストです.