11.1 標準ライブラリ関数 11.2 関数呼び出しのオーバーヘッド 11.3 大域変数 11.4 プロトタイプ宣言 11.5 関数引数

Slides:



Advertisements
Similar presentations
プログラミング 関数編 情報科学科. プログラミングにあたって C 言語では、 main 内に処理を記述 1000 行になるような大きなプログラムでは、 プログラム全体が何をしているのかを把握 することが困難になる 他人が見ると非常に理解しにくい 作成者であっても時が経てば内容を忘れて、他 人が見た時と同じ状況になる.
Advertisements

第 11 章 関数について 11.1 標準ライブラリ関数 11.2 関数呼び出しのオーバーヘッド 11.3 大域変数 11.4 プロトタイプ宣言 数学関数の自作.
A B x y z 復習 構造体変数 普通の変数 x y z 構造体変数 x y z 箱のイメージ 引き出しのイメージ
情報基礎演習B 後半第5回 担当 岩村 TA 谷本君.
関数 C 言語では、関数を組み合わせてプログラムを構成する
プログラミング論 数値積分
第13回構造体.
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
第10回関数2 (関数の利用と変数のスコープ).
プログラミング演習II 2004年10月19日(第1回) 理学部数学科・木村巌.
第4回放送授業.
プログラミング演習Ⅰ 課題2 10進数と2進数 2回目.
関数 関数とスタック.
ちょっとした練習問題① 配列iroを['R', 'W', 'R', 'R', 'W' , 'W' , 'W']を宣言して、「W」のときの配列の番号をprintfで表示するようなプログラムを記述しなさい。
プログラミング2 関数
プログラミング論 ファイル入出力
関数とポインタ 値呼び出しと参照呼び出し swapのいろいろ 関数引数 数値積分
関数と配列とポインタ 1次元配列 2次元配列 配列を使って結果を返す 演習問題
関数の定義.
第10回関数 Ⅱ (ローカル変数とスコープ).
岩村雅一 知能情報工学演習I 第9回(後半第3回) 岩村雅一
プログラミング入門2 第11回 情報工学科 篠埜 功.
第9回関数Ⅰ (簡単な関数の定義と利用) 戻り値.
プログラミング入門2 第11回 情報工学科 篠埜 功.
第7回 プログラミングⅡ 第7回
復習 前回の関数のまとめ(1) 関数はmain()関数または他の関数から呼び出されて実行される.
プログラミング言語論 第五回 理工学部 情報システム工学科 新田直也.
アルゴリズムとデータ構造 補足資料5-1 「メモリとポインタ」
高度プログラミング演習 (08).
地域情報学 C言語プログラミング 第5回 ポインタ、関数、ファイル入出力 2017年11月17日
プログラミング論 ファイル入出力
第11回 プログラミングⅡ 第11回
復習 2次元配列 4列 j = 0 j = 1 j = 2 j = 3 i = 0 i = 1 i = 2 3行
関数の再帰呼び出しとは ハノイの塔 リダイレクト レポート課題
関数への道.
第14章 ファイル操作 14.1 ファイルへの書き込み 14.2 ファイルからの読み込み 14.3 ファイルへの追加書き込み
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
岩村雅一 知能情報工学演習I 第12回(C言語第6回) 岩村雅一
疑似乱数, モンテカルロ法によるシミュレーション
メモリとメモリアドレス, ポインタ変数,関数へのポインタ渡し
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
プログラミング言語論 第六回 理工学部 情報システム工学科 新田直也.
第14章 ファイル操作 14.1 ファイルへの書き込み 14.2 ファイルからの読み込み 14.3 ファイルへの追加書き込み
岩村雅一 知能情報工学演習I 第9回(後半第3回) 岩村雅一
15.1 文字列処理の基本 15.2 文字列処理用ライブラリ関数
復習 2次元配列 4列 j = 0 j = 1 j = 2 j = 3 i = 0 i = 1 i = 2 3行
ポインタとポインタを用いた関数定義.
情報基礎演習B 後半第2回 担当 岩村 TA 谷本君.
第5回 プログラミングⅡ 第5回
オブジェクト指向言語論 第五回 知能情報学部 新田直也.
岩村雅一 知能情報工学演習I 第12回(後半第6回) 岩村雅一
プログラミング入門2 第6回 関数 情報工学科 篠埜 功.
プログラミング言語論 第九回 理工学部 情報システム工学科 新田直也.
プログラミング演習I 2003年6月11日(第9回) 木村巌.
オブジェクト指向言語論 第七回 知能情報学部 新田直也.
プログラミング言語論 第九回 理工学部 情報システム工学科 新田直也.
オブジェクト指向言語論 第七回 知能情報学部 新田直也.
オブジェクト指向言語論 第三回 知能情報学部 新田直也.
プログラミング言語Ⅰ(実習を含む。), 計算機言語Ⅰ・計算機言語演習Ⅰ, 情報処理言語Ⅰ(実習を含む。)
プログラミング演習II 2004年11月 2日(第3回) 理学部数学科・木村巌.
プログラミング入門2 第5回 配列 変数宣言、初期化について
値渡しと参照渡しについて.
第14章 ファイル操作 14.1 ファイルへの書き込み 14.2 ファイルからの読み込み 14.3 ファイルへの追加書き込み
計算技術研究会 第5回 C言語勉強会 関数(function)を使う
プログラミング演習I 補講用課題
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
プログラミング 2 静的変数.
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
Presentation transcript:

11.1 標準ライブラリ関数 11.2 関数呼び出しのオーバーヘッド 11.3 大域変数 11.4 プロトタイプ宣言 11.5 関数引数 第11章 関数について 11.1 標準ライブラリ関数 11.2 関数呼び出しのオーバーヘッド 11.3 大域変数 11.4 プロトタイプ宣言 11.5 関数引数

11.1 標準ライブラリ関数 予め定義されており、ユーザが定義・作成しなくても使える関数 ヘッダ部に以下のマクロが必要 #include <stdio.h> ← printf, scanf等の入出力関数 #include <math.h> ← sqrt, sin等の数学関数

11.2 関数呼び出しのオーバーヘッド 関数を呼び出す時、実際の計算以外のことに使われるマシンへの余分な負荷をオーバーヘッドという 関数に渡されるデータのコピーを作るための実行時間や、そのためのメモリ消費など → データ数が大量になると無視できなくなる 関数の呼び出し回数が少なくて済むプログラムに

プログラム例11.2.2 #include <stdio.h> double sum(double, double); int main(void) { int count = 5; double a[] = {1.23, 2.34, 3.45, 4.56, 12.34}; double b[] = {4.56, 5.67, 6.78, 7.89, 19.2}; double c[50]; int i; for (i = 0; i < count; i++) { c[i] = sum(a[i], b[i]); printf("%6.2f %6.2f %6.2f\n", a[i], b[i], c[i]); } return 0; double sum(double x, double y) return (x + y); プロトタイプ宣言はこれでOK 関数 sum をデータの数だけ呼出している。 (その度にオーバーヘッドの時間がかかる ので、データが大量になるとバカにならない)

プログラム例11.2.3 関数sumの呼び出しは1回 #include <stdio.h> void sum(int, double *, double *, double *); int main(void) { int count = 5; double a[] = {1.23, 2.34, 3.45, 4.56, 12.34}; double b[] = {4.56, 5.67, 6.78, 7.89, 19.2}; double c[50]; int i; sum(count, a, b, c); for (i = 0; i < count; i++) printf("%6.2f %6.2f %6.2f\n", a[i], b[i], c[i]); return 0; } void sum(int n, double *xp, double *yp, double *zp) for (i = 0; i < n; i++) { *zp = *xp + *yp; zp++; xp++; yp++; プロトタイプ宣言はこれでOK a と&a[0]は同じもの 関数sumの呼び出しは1回 ポインタの中味*zpは変化するが、 引数(ポインタ)自体は戻されない ふつうは zp[i] = xp[i] + yp[i] → 第12章

11.3 大域変数(global variable) グローバル変数 全ての関数からアクセス可能な変数 10.4で学習した局所変数(local variable)とは対立する概念 → 以下の3つのプログラム例を参照

10.4 関数と変数の可視範囲 より引用 関数内で宣言した変数は、その関数内でのみ可視 アクセス可能 変数の可視範囲 ⇒ スコープ という 変数の可視範囲 ⇒ スコープ という ある関数の中でのみ通用する変数         ⇒ 局所変数 という

この a,b のスコープは scope_rule のみ 局所変数の例―プログラム例 10.4.1― mainとscope_ruleの両方で同じ変数a,bを用いても良い int main(void) { int a = 10, b = 30; printf(“関数呼び出し前 a = %d b = %d¥n”, a, b); scope_rule(); printf(“関数呼び出し後 a = %d b = %d¥n”, a, b); return 0; } void scope_rule(void) int a, b; a = 200; b = 400; printf(“関数内部では a = %d b = %d¥n”, a, b); この a,b のスコープは main のみ 同じ変数名 a,b でも、関数毎に 別々に変数領域が割り当てられる この a,b のスコープは scope_rule のみ

関数 sum や difference に引数は不要 大域変数の例―プログラム例 11.3.1― #include <stdio.h> void sum(void); void difference(void); double x, y; int main(void) { x = 12.5; y = 56.7; sum(); difference(); return 0; } void sum(void) printf(“和は %f¥n”, x + y); void difference(void) printf(“差は %f¥n”, x - y); この x,y のスコープは全ての関数 関数 sum や difference に引数は不要 関数 sum や difference で新たに変数宣言していない ので、x,y といえば、4行目で宣言された変数 x,y を指す 一見、便利!

混在する場合―プログラム例 11.3.2― 大域変数を使わないプログラミングを心がけよう! この u,v のスコープは全ての関数 #include <stdio.h> void scope_rule(void); int u, v; int main(void) { u = 10; v = 20; printf(“関数の呼び出し前 %d %d¥n”, u, v); scope_rule(); printf(“関数の呼び出し後 %d %d¥n”, u, v); return 0; } void scope_rule(void) u = 100; v = 200; printf(“関数内では %d %d¥n”, u, v); この u,v のスコープは全ての関数 混乱を招くので 乱用しない 関数内での局所変数名に大域変数名と同じ ものを用いても構わない。 この u,v のスコープは scope_rule のみ 大域変数を使わないプログラミングを心がけよう!

11.4 プロトタイプ宣言 プロトタイプ宣言とは?(教科書p.78参照) プログラム例 10.1.1 プロトタイプ宣言 #include <stdio.h> double sum(double x, double y); int main(void) {   ・ } double sum(double x, double y) double z; z = x + y; return z; sum という関数を使う その詳細は後で定義 引数は double 型2個 戻り値は double 型 1行でこれだけの意味を持つ sum という関数の定義部

プログラム例 11.4.2 プロトタイプ宣言では、 関数の引数となる変数名は 省略できる 当然だが、関数定義では 仮引数は必要 #include <stdio.h> int foo(int, int, double); double bar(double, double); int main(void) { ...; return 0; } int foo(int u, int v, double w) double bar(double m, double n) プロトタイプ宣言では、 関数の引数となる変数名は 省略できる 当然だが、関数定義では 仮引数は必要

11.5 関数引数 関数の引数として、関数へのポインタも使える これまでに習ってきた例:実数 x,y が引数 プログラム例 11.5.1 より double integral(double lower, double upper, int n, double (*f)(double)) { double h, sum; int i; sum = 0.0;   ・ } 変数なら   double f ポインタなら double *f となるところ… これまでに習ってきた例:実数 x,y が引数 プログラム例 10.1.3 より double sum(double x, double y) { double z; z = x + y; return z; }

11.5 関数引数 プログラム例 11.5.1 #include <stdio.h> #include <math.h> double circle(double); double parabola(double); double integral(double, double, int, double (*f)(double)); int main(void) { printf("%f¥n", integral(0.0, 1.0, 100, circle)); printf("%f¥n", integral(0.0, 1.0, 100, parabola)); return 0; } double型関数へのポインタが 引数であることを意味する 1行目では関数 circle を, 2行目では関数 parabola を 実引数としている 次のスライドに続く

プログラム例 11.5.1 関数 circle、関数 parabola と 関数 integral の関数定義部 double integral(double lower, double upper, int n, double (*f)(double)) { double h, sum; int i; sum = 0.0; h = (upper - lower) / n; for (i = 1; i < n; i++) sum += f(lower + i * h); return 0.5 * h * (2.0 * sum + f(lower) + f(upper)); } double circle(double x) return sqrt(1.0 - x * x ); double parabola(double x) return x * x; f(…)の部分では、main で呼ばれたときに 実引数となっている関数を呼び出す integral(…, circle) なら関数 circle を呼び、 integral(…, parabola) なら関数 parabola を呼ぶ

スキルアップタイム 1 以下はプログラム例11.2.2の改変。何を変えたか考えながら実行してみよう #include <stdio.h> double sum(double x, double y); int k = 0; int main(void) { int i, count = 8; double a[] = {1.23, 2.34, 3.45, 4.56, 5.67, 6.78, 7.89, 8.91}; double b[] = {2.34, 3.45, 4.56, 5.67, 6.78, 7.89, 8.91, 1.23}; double c[8]; for (i = 0; i < count; i++) { c[i] = sum(a[i], b[i]); printf("%7.3f %7.3f %7.3f %3d\n", a[i], b[i], c[i], k); } return 0; double sum(double x, double y) k++; return (x + y);

スキルアップタイム 2 以下はプログラム例11.2.3の改変。何を変えたか考えながら実行してみよう #include <stdio.h> void sum(int n, double *x, double *y, double *z); int k = 0; int main(void) { int i, count = 8; double a[] = {1.23, 2.34, 3.45, 4.56, 5.67, 6.78, 7.89, 8.91}; double b[] = {2.34, 3.45, 4.56, 5.67, 6.78, 7.89, 8.91, 1.23}; double c[8]; sum(count, a, b, c); for (i = 0; i < count; i++) printf("%7.3f %7.3f %7.3f %3d\n", a[i], b[i], c[i], k); return 0; } void sum(int n, double *xp, double *yp, double *zp) int i; k++; for (i = 0; i < n; i++) { *zp = *xp + *yp; zp++; xp++; yp++;

スキルアップタイム 3 Integral 台形公式 プログラム例11.5.1を、何を求めているのか良く考えながら実行してみよう 1 circle 0       1 1 parabola 台形公式 0       1