プログラミング入門2 第6回 関数(2) 芝浦工業大学情報工学科 青木 義満 I’ll get started with Introduction and Conventional works around our study, then mention our motivation and goal. Next, I’ll explain our 3D Face Modeling Method and its medical application. Finally, I’ll conclude this presentation with some future works. 芝浦工業大学情報工学科 青木 義満
今回の講義内容 関数 入出力と文字 (p.198~) 文字列の基本 (p.208~) 配列データの受け渡し (p.130~) プログラミング入門2
配列データをそのまま受け取る関数が必要! 例えば・・・・ 最大体重と最小体重を求めるプログラム(一部) double weight[NUM]; double min, max; min = max = weight[0]; for( i= 1; i < NUM; i++ ){ if ( weight[i] > max ) max = weight[i]: if ( weight[i] < min ) min = weight[i]: } 最大値・最小値を求める処理 配列weightのデータを受け取り,その要素の中で最大・最小を求める 配列データをそのまま受け取る関数が必要! プログラミング入門2
関数での配列データの必要性 整数値を2つ受け取り,最大値を求める関数 整数値を3つ受け取り,最大値を求める関数 呼び出し側 呼び出し側 int maxof( int x, int y ) { ・・・・・・ } 関数定義部 呼び出し側 maxof(a, b); int maxof( int x, int y,int z ) { ・・・・・・ } 関数定義部 呼び出し側 maxof(a, b,c); 判定する値の数が増えたら・・・ 配列でまとめてデータを渡す! プログラミング入門2
配列の受け渡し (p.130) 構文 max_e = maxof( eng, 5 ); int eng[5]; /* 英語の点数 */ int max_e; /* 英語の最高点 */ 配列engに5つの得点データを読み込み max_e = maxof( eng, 5 ); main関数(呼び出し側) 配列名 ([]は不要) 配列の要素数 int maxof( int vc[], int no ) { ・・・配列vc[0]~vc[4] を使った処理・・・ } 関数 int の配列を受け取 る時の宣言 配列の要素数 eng[4] eng[3] eng[2] eng[1] eng[0] main関数 vc[4] vc[3] vc[2] vc[1] vc[0] maxof関数 main関数はengという配列を渡し,関数maxofは,その配列データをvcという名前で受け取る。 プログラミング入門2
例題 関数による配列の受け渡し ソースファイル名:list0611.c (p.130) 英語の点数と数学の点数を配列として受け取り,それぞれの最高点を求める関数を作成せよ #include <stdio.h> #define NUMBER 5 int max_of(int vc[], int no) { int i; int max = vc[0]; for (i = 1; i < no; i++){ if (vc[i] > max) max = vc[i]; } return (max); int main(void) int i; int eng[NUMBER]; int mat[NUMBER]; int max_e, max_m; printf("%d人の点数を入力してください。\n", NUMBER); for (i = 0; i < NUMBER; i++) { printf("[%d] 英語:", i + 1); scanf("%d", &eng[i]); printf( " 数学:"); scanf("%d", &mat[i]); } max_e = max_of(eng, NUMBER); max_m = max_of(mat, NUMBER); printf("英語の最高点=%d\n", max_e); printf("数学の最高点=%d\n", max_m); return (0); 関数による 配列の受け取り 配列を関数に受け渡し プログラミング入門2
関数呼び出しと引数の引渡し過程 (先週の復習) 関数呼び出しと引数の引渡し過程 (先週の復習) main関数 実引数na, nbの値が,仮引数x, yに それぞれコピーされる (変数そのものでなく,中に格納されている値 が受け渡される!) 重要 int main(void) { int na, nb, max; na = 24; nb = 62; ・・・・ } 実引数 max = maxof( na, nb ); 62 62 24 int maxof( int x, int y ) { if (x > y) return (x); else return (y); } 62 仮引数 returnか,関数最後の } で 呼び出し元へ戻る プログラミング入門2
受け取った配列への書込み (p.132) 詳しい理由は,後日の”ポインタ”で説明 関数への値の受け渡し(配列以外) 重要 実引数の値が,仮引数にコピーされる (変数そのものでなく,中に格納されている値が受け渡される!) 重要 関数への値の受け渡し(配列の場合) 呼び出された側の関数で仮引数として受け取った配列は,呼び出し側で与えた実引数の配列そのものである。 重要 詳しい理由は,後日の”ポインタ”で説明 プログラミング入門2
表示結果は? 受け取ったデータへの書込み 例1 void set_value( int x, int y ) { x = 0; y = 0; 受け取ったデータへの書込み 例1 #include <stdio.h> void set_value( int x, int y ) { x = 0; y = 0; } int main(void) int na, nb; na = 10; nb = 5; set_value( na, nb ); printf(“na= %d\n”, na ); printf(“nb= %d\n”, nb ); return (0); 表示結果は? プログラミング入門2
表示結果は? 受け取った配列への書込み 例2 = void set_value( int vc[] ) { vc[0] = 0; ? 受け取った配列への書込み 例2 #include <stdio.h> void set_value( int vc[] ) { vc[0] = 0; vc[1] = 0; } int main(void) int x[2]; x[0] = 10; x[1] = 5; set_value( x ); printf(“x[0]= %d\n”, x[0] ); printf(“x[1]= %d\n”, x[1] ); return (0); ? 表示結果は? x[1] x[0] main関数 vc[1] vc[0] set_value関数 = ? プログラミング入門2
例題 ~受け取った配列への書込み ソースファイル名:list0612.c (p.132) 内容:受け取った配列の全要素の値を0にする関数 例題 ~受け取った配列への書込み ソースファイル名:list0612.c (p.132) 内容:受け取った配列の全要素の値を0にする関数 #include <stdio.h> void int_set( int vc[], int no ) { int i; for (i = 0; i < no; i++) vc[i] = 0; } int main(void) int i; int ary1[] = {1, 2, 3, 4, 5}; int ary2[] = {3, 2, 1}; int_set(ary1, 5); int_set(ary2, 3); for (i = 0; i < 5; i++){ printf(“ary1[%d] = %d\n”, i, ary1[i]); } for (i = 0; i < 3; i++){ printf(“ary2[%d] = %d\n”, i, ary2[i]); return (0); プログラミング入門2
変数の有効範囲と寿命 (p.140) ①~④ : どんな値が表示? いろいろな場所にある x, それぞれの値はいくつ? int x=7; ① #include <stdio.h> int x = 77; void print_x1(void) { int x = 777; printf( "x = %d\n", x ); } void print_x2(void) int main(void) { int x=7; printf( "x = %d\n", x ); print_x1(); print_x2(); return(0); } ① ② ③ ④ ①~④ : どんな値が表示? プログラミング入門2
変数の有効範囲と寿命 (p.140) ファイル有効範囲,ブロック有効範囲 int x=7; int x = 77; ファイル有効範囲 #include <stdio.h> int x = 77; void print_x1(void) { int x = 777; printf( "x = %d\n", x ); } void print_x2(void) int main(void) { int x=7; printf( "x = %d\n", x ); print_x1(); print_x2(); return(0); } ブロック有効範囲 (main関数内) ファイル有効範囲 ブロック有効範囲 (関数内) ・ファイル有効範囲: プログラム全体に渡って使用することができる(main関数,自作関数) ・ブロック有効範囲:ある関数内のみで仕様できる プログラミング入門2
変数の有効範囲と寿命 (p.140) ファイル有効範囲,ブロック有効範囲 #include <stdio.h> int x = 77; int main(void) { int x=7; printf( "x = %d\n", x ); print_x1(); print_x2(); return(0); } ファイル有効範囲 ブロック有効範囲 (main関数内) ファイル有効範囲とブロック有効範囲を持つ同じ名前の変数が存在する場合は,ブロック有効範囲のものが“見えて”,ファイル有効範囲のものは隠される! プログラミング入門2
変数の有効範囲と寿命 (p.140) いろいろな場所にある x, それぞれの値はいくつ? int x=7; ① ② ③ ④ ① 7 #include <stdio.h> int x = 77; void print_x1(void) { int x = 777; printf( "x = %d\n", x ); } void print_x2(void) int main(void) { int x=7; printf( "x = %d\n", x ); print_x1(); print_x2(); return(0); } ① ② ③ ④ ① 7 ② 777 ③ 77 ④ 7 表示結果 プログラミング入門2
用途に応じて,上手に使い分ける 変数の有効範囲と寿命 (p.140) プログラム全体(main関数とその他の関数内)で変数を使いたい場合 → ファイル有効範囲の変数を使う → 宣言は#include , #defineの後,main文の前 ※使いすぎはメモリーの消費量大 ある関数内のみで使用する変数 → ブロック有効範囲の変数を使う → 使いたい関数内で宣言 ※ 関数を抜けると,メモリー上から消滅 用途に応じて,上手に使い分ける プログラミング入門2
printf( “fun2 was called\n" ); ファイル有効範囲を持つ変数の使用例 複数の関数の呼び出し回数をカウント ソースファイル名:count.c #include <stdio.h> int count = 0; void func1(void) { printf( “fun1 was called\n" ); count++; } void func2(void) printf( “fun2 was called\n" ); int main(void) { int i; func1(); func2(); for(i=0; i < 5; i++){ } for(i=0; i < 3; i++){ printf( “count = %d\n", count ); return(0); ファイル有効範囲 プログラミング入門2
表示結果を確認 自動記憶域期間と静的記憶域期間 ソースファイル名:list0619.c 内容: 変数の寿命を理解する ax sx fx 内容: 変数の寿命を理解する #include <stdio.h> int fx = 0; void func(void) { static int sx = 0 ; int ax = 0; printf("%3d%3d%3d\n", ax++, sx++, fx++); } int main(void) int i; puts(" ax sx fx"); puts("----------"); for (i = 0; i < 10; i++) func(); return (0); 静的記憶域期間 表示結果を確認 静的記憶域期間 自動記憶域期間 ax sx fx -------------- 0 0 0 0 1 1 0 2 2 0 3 3 ・・・・・・・・ ・・・・・・・・ 自動記憶域期間 プログラミング入門2
演習課題1 int search_value( int x[ ], int key ); 配列データ中からの値の探索プログラム 以下の手順により,配列中にある値のデータがあるかどうかを判定する関数を作成し,動作を確認せよ。見つかった場合には,その要素番号を,見つからなかった場合には,-1を返すようにせよ。 int search_value( int x[ ], int key ); 探索対象データ 5個の整数値が格納された配列 探索キーとなる値 探したい値 見つかったらそのデータの要素番号を 見つからなかったら-1を返す ・int型配列(要素5)を用意 ・配列にキーボードから5個の整数値を入力,配列に値をセット ・探したい値をキーボードから入力 ・search_value関数に配列データと探したい値を渡し,データをサーチ ・search_value関数の返却値により,結果を表示 見つかった場合には,データが見つかった位置(要素番号)と値 見つからなかった場合には,見つからなかった旨 を表示せよ。 プログラミング入門2
演習課題2 void display_graph( int tensu[ ], int num ); 人数 1~20人分のテストの点数を繰り返し入力し,データに応じて以下のような分布グラフを表示するプログラムを作成せよ。 ただし,分布グラフの表示には以下の関数を作成・使用せよ。 分布グラフ A 80 - 100 : **** B 70 - 79 : ******* C 60 - 69 : **** D 0 - 59: ** void display_graph( int tensu[ ], int num ); 点数データの格納 されている配列 人数 ※余裕があれば,全得点データの平均と分散の値を表示する関数 void heikin_bunsan( int tensu[ ], int num ); を作成し,分布グラフと共に結果を表示せよ。 プログラミング入門2