(5)関数 その1 システム科学領域 日浦 慎作 関数とは • 一連の仕事をひとつにまとめたもの 引数 • 簡単な指示で複 雑な仕事をさせる ことができる • 指示を出すほう は作業方法を知 らなくてもよい • あちこちから何度 でも同じ仕事を依 頼できる • 少し違った要求な らこたえることが 出来る 牛丼並ひとつ 戻り値 牛丼関数 はいよっ 280円 牛丼,大盛り, つゆだく ねぎだく はいよっw 400円 仕事: ・ご飯を 丼に盛る ・肉・玉葱・ つゆを入れる ・客に出す ・金を取る 関数 関数の例 • 整数を自乗する関数 #include <stdio.h> int square (int x); 関数の宣言(関数の概要の記述) int main(void) { int y; y = square(5); printf(“result is %d\n”, y); return 0; } int square (int x) { return x * x; } 関数の定義 (関数そのもの記述) 関数の「いいところ」 • 関数の中身を知らなくていい – 「どういう結果を生じるか」のみ知っていればOK – プログラムが見やすく,分かりやすくなる • 同じ処理を何度も書かなくて良い – 同じ処理をするたびに,呼び出せばよい • 処理を「一人立ち」させることが出来る – 関数を独立に作成・デバッグし, 完成したものとして提供できる – 他人様にも簡単に使っていただける 関数の「精神」 • ブラックボックス化 – 関数の中身は必ずしも知らなくてよい – 処理は複雑でも,提供する機能は分かりやすい • 例えば,sin( ) とか sqrt( ) など – 確実に動作する • バグ(不具合)がよく除かれている – 明示的な結果以外の作用(副作用)がない • 他の変数の値が勝手に変わるなど 関数の「仕様」 • どんな「引数」を取るのか – 引数の数,型 (int, double, ..) • どんな「戻り値」を返すのか – 戻り値の有無,戻り値の型 – 戻り値無しの場合は void を使う • 関数の機能 – どのような引数を与えるとどのように動作し, どのような結果(画面入出力,戻り値など)を もたらすのか 関数の使い方 • どこからでも呼び出すことが出来る y = sq (i); 普通の式 printf(“val = %d\n”, sq(j) ); 関数の引数で z = sq( sq (2) ); (同上) • 戻り値を利用することも,使わないのもOK • 引数の型に注意 (int に double を入れる等) 関数の中身 int max (int a, int b); int max (int a, int b) { int result; 戻り値の型 } if(a > b) { result = a; } else { result = b; } return result; 関数の宣言(関数の概要の記述) 引数の名前と型 関数内部で変数を定義できる (有効範囲はこの関数内だけ) 関数の定義 (関数そのもの記述) return で関数を抜けることが出来る その際に戻り値を指定できる 関数の注意事項 • 関数内で変数を定義したり値を変更しても, 呼び出し側には影響しない (テキスト ポイント8) • 呼び出し側に影響を与える3つの方法 – 戻り値で情報を戻す – ポインタを使う(次回講義で説明) – 「配列」を使う 再帰呼び出し int frac(int n) { int r; if(n == 1) r = 1; else r = n * frac(n-1); return r; } • 関数は自分自身を呼 び出すことが出来る 再帰呼び出し 120 int frac(int n) { int r; if(n == 1) r = 1; else r = n * frac(n-1); return r; } frac(5) frac(4) frac(3) frac(2) frac(5-1) frac(4-1) frac(3-1) frac(2-1) 24 6 2 frac(1) 1 • 呼び出した関数の状態は保持されている • どこかで再起呼び出しをやめて return しなけ ればならない (6)配列 その1 システム科学領域 日浦 慎作 配列とは • 同じ形式のデータを並べたもの • 名前で指定するのではなく,番号で指定 番号 0 1 2 3 4 5 6 データ 85 72 48 96 84 77 58 #define NUM 30 int main(void) { int i; int main(void) { int intseiseki[30]; i; int seiseki[NUM]; seiseki[0] = 10; seiseki[1] seiseki[0]==20; 10; seiseki[1] = 20; for (i = 0; i < 30; i++) { seiseki[i]); for (i =printf(“%d\n”, 0; i < NUM; i++) { } printf(“%d\n”, seiseki[i]); ….. } ….. C言語での配列 • 0から始まる – – – – 1から始まる言語もある int data[10] とした場合,使える添え字は 0~9 添え字は整数値しか使えない (double 使用不可) 添え字に変数や数式を使うことが出来る • 要素数は固定 – 途中で増やしたり減らしたり出来ない – 添え字が要素数を超えているかどうかはチェックされない (超えてしまうとプログラムが異常動作する) • どのような型でも配列に出来る – int, double, その他なんでも可能 初期値の入れ方 番号 0 1 2 3 4 5 6 データ 85 72 48 96 84 77 58 int seiseki[7] = {85, 72, 48, 96, 84, 77, 58}; もしくは int seiseki[] = {85, 72, 48, 96, 84, 77, 58}; • 添え字を省略することも出来る • 初期値は要素より少なくても良い 二次元配列 • 二次元配列は以下のように書く int data[5][10]; (int data[5,10]; は間違い) • 3次元以上も可能 • 初期化も可能 – int data[4][3] = { {5, 6, 3}, {4, 5, 2}, {6, 3, 1}, {1, 8, 9} }; 配列を使うと • 以下の課題などは簡単に実装できる • 数量の制限を外すことが出来る – 課題 5人の身長を入力すれば,その平均身長を 計算するプログラムを作成せよ. → n 人の身長を入力すれば.. – 課題 4つの整数値を読み込んで,その最大値と 最小値を求めるプログラ ムを作成せよ. → n 個の整数値を読み込んで.. など. (7)関数その2 配列を引数に取る関数 システム科学領域 日浦 慎作 配列を受け取る関 数であることを宣言 する 配列を引数に渡す int minimum(int data[], int num); int main(void) { int seiseki[10] = {70, 85, … }; int min; 呼び出し側では, 配列の名前のみ指 定すればよい min = minimum(seiseki, 10); printf(“minimum is %d\n”, min); } int minimum(int data[], int num) { ….. 受け取り側では, } 配列の要素数を指 定する必要は無い 配列の中身の変更 int change(int data); int change(int data[], int num); int main(void) { int d = 70; int main(void) { int d [10] = {70, 85, … }; change (d); printf(“d is %d\n”, d); change (d, 10); printf(“d[0] is %d\n”, d[0]); } } int change(int data) { data = 0; } int change(int data[], int num) { data[0] = 0; } 値は変わらない 値が変わる const 修飾子 • const は値の変更を禁じる • 変数を const にした場合:値の変更が不可能 const int a = 10; a = 20; エラー • 引数を const にした場合:値が変更されない int func (const int data[], int n); とすると,func 内で data に値を代入できない int func (const int data[], int n) { data[0] = 10; エラー } 引数を関数に渡す仕組み(1) int change(int data); int main(void) { int d = 70; 実行位置 change (d); printf(“d is %d\n”, d); } int change(int data) { data = 0; } 70 d コピーが起こる 0 値渡し data 引数を関数に渡す仕組み(2) データが格納される領域は共通 int change(int data[], int num); int main(void) { 実行位置 int d [7] = {70, 85, … }; change (d, 7); printf(“d[0] is %d\n”, d[0]); } int change(int data[], int num) { data[0] = 0; } 0 d data 1 70 0 85 2 … 3 4 5 6 要素数は いくらでも良い 二次元配列の引数渡し • 二次元配列の場合は,引数の個数を指定す る必要がある – int func(int data[][]); エラー – int func(int data[2][3]); OK – int func(int data[][3]); OK – int func(int data[2][]); エラー 二次元配列 int change(int data[][3]); int main(void) { int d [2][3] = {{1, 2, 3}, {4, 5, 6}}; d data change (d); printf(“d[1][2] is %d\n”, d[1][2]); } [0][0] 1 [0][1] 2 [0][2] 3 [1][0] 4 [1][1] 5 [1][2] 06 要素数は いくらでも良い int change(int data[][3]) { data[1][2] = 0; (C言語では } チェックされない) data[a][b] は,a * 3 + b 番の要素(この計算を実行時に行うために3が要る)
© Copyright 2024 ExpyDoc