関数 C 言語では、関数を組み合わせてプログラムを構成する

Slides:



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

プログラミング入門2 芝浦工業大学情報工学科青木 義満 第6回関数(2). プログラミング入門2 2 今回の講義内容 関数 配列データの受け渡し ( p.130 ~) 入出力と文字 ( p.198 ~) 文字列の基本 ( p.208 ~)
情報・知能工学系 山本一公 プログラミング演習Ⅱ 第5回 関数(1) 情報・知能工学系 山本一公
解答 1 複素数を構造体として定義し、二つの複素数の積(結果は複素数)を返す 関数 を定義せよ。
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
システムプログラミング 第5回 情報工学科 篠埜 功 ヒアドキュメント レポート課題 main関数の引数 usageメッセージ
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
C言語 第2講 生物機能制御学講座 濱田 農学部7号館209室.
第10回関数2 (関数の利用と変数のスコープ).
プログラミング入門2 第6回 関数(2) 芝浦工業大学情報工学科 青木 義満
プログラミング演習(2組) 第12回
記憶クラス 変数をどのような記憶領域に割り当てるかを指定するのが記憶クラス 記憶クラスには、自動変数、静的変数、外部変数などがある。
問題 1 フィボナッチ数列 xn は次で定義される。
プログラミング演習Ⅰ 課題2 10進数と2進数 2回目.
プログラミング入門2 第2回 複合文、繰り返し 情報工学科 篠埜 功.
関数 関数とスタック.
精密工学科プログラミング基礎Ⅱ 第3回資料 今回の授業で習得してほしいこと: 2次元配列の使い方 (前回の1次元配列の復習もします.)
プログラミング入門2 第5回 関数(1) 芝浦工業大学情報工学科 青木 義満
ちょっとした練習問題① 配列iroを['R', 'W', 'R', 'R', 'W' , 'W' , 'W']を宣言して、「W」のときの配列の番号をprintfで表示するようなプログラムを記述しなさい。
プログラミング2 関数
関数とポインタ 値呼び出しと参照呼び出し swapのいろいろ 関数引数 数値積分
関数と配列とポインタ 1次元配列 2次元配列 配列を使って結果を返す 演習問題
関数の定義.
第10回関数 Ⅱ (ローカル変数とスコープ).
Cプログラミング演習 第7回 メモリ内でのデータの配置.
プログラミング入門2 第2回 型と演算 条件分岐 篠埜 功.
岩村雅一 知能情報工学演習I 第9回(後半第3回) 岩村雅一
第9回関数Ⅰ (簡単な関数の定義と利用) 戻り値.
復習 前回の関数のまとめ(1) 関数はmain()関数または他の関数から呼び出されて実行される.
プログラミング言語論 第五回 理工学部 情報システム工学科 新田直也.
地域情報学 C言語プログラミング 第5回 ポインタ、関数、ファイル入出力 2017年11月17日
四則演算,変数 入力文,出力文,代入文, ライブラリ関数
復習 2次元配列 4列 j = 0 j = 1 j = 2 j = 3 i = 0 i = 1 i = 2 3行
関数への道.
岩村雅一 知能情報工学演習I 第9回(後半第3回) 岩村雅一
整数データと浮動小数データ.
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
岩村雅一 知能情報工学演習I 第12回(C言語第6回) 岩村雅一
疑似乱数, モンテカルロ法によるシミュレーション
メモリとメモリアドレス, ポインタ変数,関数へのポインタ渡し
C言語 はじめに 2016年 吉田研究室.
岩村雅一 知能情報工学演習I 第9回(後半第3回) 岩村雅一
復習 2次元配列 4列 j = 0 j = 1 j = 2 j = 3 i = 0 i = 1 i = 2 3行
プログラミング入門2 第6回 関数 情報工学科 篠埜 功.
復習 breakとcontinueの違い int i; for (i = 1; i <= 100; i++) { ・・・処理1・・・・
復習 Cにおけるループからの脱出と制御 break ループを強制終了する.if文と組み合わせて利用するのが一般的. continue
11.1 標準ライブラリ関数 11.2 関数呼び出しのオーバーヘッド 11.3 大域変数 11.4 プロトタイプ宣言 11.5 関数引数
第5回 プログラミングⅡ 第5回
復習 breakとcontinueの違い int i; for (i = 1; i <= 100; i++) { ・・・処理1・・・・
オブジェクト指向言語論 第五回 知能情報学部 新田直也.
精密工学科プログラミング基礎 第7回資料 (11/27実施)
プログラミング入門2 第2回 型と演算 条件分岐 篠埜 功.
cp-3. 計算 (C プログラミング演習,Visual Studio 2019 対応)
岩村雅一 知能情報工学演習I 第12回(後半第6回) 岩村雅一
プログラミング入門2 第6回 関数 情報工学科 篠埜 功.
精密工学科プログラミング基礎Ⅱ 第2回資料 今回の授業で習得してほしいこと: 配列の使い方 (今回は1次元,次回は2次元をやります.)
第7章 そろそろ int 以外も使ってみよう! ~データ型 double , bool~
関数と再帰 教科書13章 電子1(木曜クラス) 2005/06/22(Thu.).
プログラミング演習I 2003年6月11日(第9回) 木村巌.
四則演算,変数 入力文,出力文,代入文, ライブラリ関数
第10回 関数と再帰.
オブジェクト指向言語論 第三回 知能情報学部 新田直也.
プログラミング言語Ⅰ(実習を含む。), 計算機言語Ⅰ・計算機言語演習Ⅰ, 情報処理言語Ⅰ(実習を含む。)
プログラミング演習II 2004年11月 2日(第3回) 理学部数学科・木村巌.
プログラミング入門2 第5回 配列 変数宣言、初期化について
計算技術研究会 第5回 C言語勉強会 関数(function)を使う
プログラミング演習I 補講用課題
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
Presentation transcript:

関数 C 言語では、関数を組み合わせてプログラムを構成する pritnf(), scanf() などは、処理系があらかじめ備えている標準ライブラリ関数 math.h で定義されている算術関数(sin,cos,sqrt…)も標準ライブラリ関数の 1 つ データを与えて、それに基づき何か動作をおこなうものが関数。 数学の関数 y = f(x) のイメージ f(x) x を与える f(x) を計算して返す f(x) はある意味ブラックボックス。内部でどのような計算をするかは具体的な処理内容に依存。数学の場合は、引き数は実数、返却値も実数の場合がほとんど。

数学で言う関数 プログラミング言語によっては、 関数(ファンクション)---- 数学的な関数 数学で言う関数とは、引数によって決まる値を求める(計算あるいは表から) その値は引数によってのみ決まる。もっと言えば、同じ値であれば、何回 計算しても、結果は同じになる。(副作用をもたない。) C言語で言う関数とはもっと広い。 pritnf(), scanf() などは、関数の値ではなくその副作用(printf()では、引数がディスプレイに表示される。また、scanf()ではキーボードから入力した数値等が指定された変数に代入される。)のために使用される。 プログラミング言語によっては、 関数(ファンクション)---- 数学的な関数 手続き(サブルーチン)------  副作用を目的とする と区別するものもある。

C 言語の関数例 #include <math.h> main() { double x, y; scanf(“%lf”, &x); y = sin(x); printf(“%f\n”,y); } 算術ライブラリ関数 sin() を x を引数として呼び出して(call)、変数 y に sin(x) の返却値(戻り値)を代入。 main() { int code; code = getchar(); printf(“%c\n”, code); } ライブラリ関数 getchar() を引数無しで呼び出し、変数 code に getchar() の返却値を代入。 標準ライブラリ関数およびユーザー関数を組み合わせて、プログラムを作成する のが C 言語の特徴。

自分で関数を定義する C 言語を含む多くの言語では、ユーザが自分の関数を定義してプログラム中で使用出来る(ユーザー関数)。 長いプログラムは、個々の個別処理作業を行う部品の集合として捉えるとプログラムしやすい。必要に応じて、メインプログラムから呼び出す部品(部分)をサブルーチンという。 main() { /* 長い main 文 */ int i; ... } main() { data_yomikomi(); data_syori(); data_syuturyoku(); } C 言語の関数(ユーザー関数を含む)はサブルーチンと似ているが返却値(戻り値)を持ちうる点が異なる。

具体例 商品の金額を入力し、消費税込みの支払い金額を計算するプログラム main() { int price, tax, payment; scanf(“%d”, &price); tax = price*0.05; payment = price + tax; printf(“%d\n”, payment); } ユーザ関数を定義しないで、全て main文として書いたプログラム。 商品金額を引数として受けとり、支払い金額を返却値として返すユーザ関数 shiharai を定義してみる。 商品金額 (int) 関数呼び出し側 shiharai 支払い金額 (int)

ユーザー関数の定義 int shiharai(int price) { int tax, payment; 返却値の型 関数名 仮引数の宣言 関数頭部 int shiharai(int price) { int tax, payment; tax = price * 0.05; payment = price + tax; return payment; } 関数頭部および関数本体に現れる引数 price は、具体的な値が格納されていない仮引数。 関数本体 関数本体では、普通にプログラムを書く(変数宣言など)。 返却値を持つ関数の場合、返却値を return 文により、関数呼び出し元に返す必要がある。 関数本体で計算した payment を、関数 shiharai の返却値として呼び出し元に返す。return 文は、後ろに書かれた式を評価し、その値を関数の返却値として呼び出し側へ返す。

1) 返却値をもつ関数は、返却値の型を明示しなければならない。 2) 関数名は自由に付けてよい(C 言語のキーワードを除く)。 3) 関数の呼び出し側から関数へデータを受け渡すには引数を用いる。  呼び出し側で指定する引数を実引数、関数側で指定する引数を仮引数と呼ぶ。 int shiharai(int price) { int tax, payment; tax = price * 0.05; payment = price + tax; return payment; } 商品金額 (int) 関数呼び出し側 shiharai 支払い金額 (int) 関数が呼び出されるまでは、関数側の引き数には具体的なデータ(値)は格納されていないので仮引数と呼ぶ。左の例では price が仮引き数。 ユーザ関数で宣言された変数は、ユーザ関数の内部でのみ有効(局所変数)。

ユーザー関数の呼び出し 関数返却値の型、関数名、引数の int shiharai(int); 型を指定するプロトタイプ宣言 main() { int price, payment; scanf(“%d”, &price); payment = shiharai(price); printf(“%d\n”, payment); } int shiharai(int price) int tax, payment; tax = price * 0.05; payment = price + tax; return payment; 関数 shiharai の呼出し (function call) 。この price は実引数(具体的な値が格納されている)。 返却値を変数 payment に代入。 関数呼出に際して、仮引数 price は 実引数 price の値で初期化される。 main 文の変数 price, payment と、 関数定義部の変数 price, payment は 別物であることに注意!

関数のプロトタイプ宣言 ユーザが自前の関数を定義するとき、一般に関数プロトタイプの宣言が必要。 関数の名前、関数が返却するデータの型、および引き数の型と個数、を関数プロトタイプと呼ぶ。(プロトタイプ prototype=原型、模範、手本の意) int fn1(int); int 型の引数 1 つを受け取り int を返す関数 fn1 double 型の引数 2 つを受け取り、 double を返す関数 fn3 double fn3(double, double); void fn4(char); char 型の引数 1 つを受け取り、 返却値を持たない関数 fn4 関数プロトタイプ宣言によって、処理系(コンパイラ)は、関数が正しく呼び出されているかのチェックを行う。 関数プロトタイプ宣言をしないと、定義した関数の返却値の型は 暗黙のうちに int と解釈される。(思わぬ結果を招く場合があるので注意)

関数呼び出しの値渡し 関数呼び出し側 仮引数 関数側 実引数 main() { int price, payment scanf("%d", &price); payment = shiharai(price); } int shiharai(int price) { int tax, payment; ... return payment; } 値(実引数) 返却値 実引数 関数 shiharai 側の仮引数は、関数呼び出し側の実引数で初期化される(実引数の値が仮引数にコピーされる)。これを値渡し(call by value)という。 関数呼び出し側で宣言された変数と、関数側で宣言された変数は互いに独立。 同じ変数名であっても別の変数として取り扱われる(局所変数)。

局所変数 関数定義部(関数頭部と関数本体)で宣言された変数は、関数(もしくはブロック)の中でのみ有効。これを局所変数(ローカル変数)と呼ぶ。 main() { int x, y, z; ... } int function_1(int x) int i, y; 変数 x, y, z は main 文の中でのみ有効な局所変数。 function_1 で宣言されている変数 i と y は main文 からは見えない。 変数 x, y, i はこのブロックの中でのみ有効。 main 文で宣言されている変数とは独立無関係。 変数が有効な範囲をスコープ (scope) という。局所変数のスコープは、それが宣言された関数本体に限られる。これをブロックスコープという。 局所変数を用いることにより、外部(他の関数など)から影響を受けない 変数の使用が可能になる。(変数の隠ぺい)

局所変数のメモリ上の配置 ... ... ブロックスコープを持つ変数は変数名が同じであっても互いに独立。 int shiharai(int); main() { int price, payment; scanf(“%d”, &price); payment = shiharai(price); printf(“%d\n”, payment); } int shiharai(int price) int tax, payment; tax = price * 0.05; payment = price + tax; return payment; メモリ上の変数の配置(処理系によって異なる) main ブロック中で宣言された変数 shiharai ブロック中で宣言された変数 ... payment payment price price tax ... メモリ空間 ブロックスコープのお陰で、外部に隠ぺいされた変数が利用できる。関数内部で定義された変数はその関数内だけのみ有効。

様々なユーザ関数例 1 double fn(double); main() { double x = 0.0, y; do{ y = fn(x); printf("%f %f\n", x, y); x += 0.1; }while(x <= 10); } double fn(double x) double tmp; tmp = exp(-0.1*x)*sin(x); return tmp; 数学の関数 y = exp[–0.1*x] sin(x) である。 計算結果をリダイレクションを用いてファイルに書き出し、gnuplot でグラフに描く。 % ./a.out > data % gnuplot G N U P L O T Linux version 3.7 ...... gnuplot > plot "data" gnuplot > quit %

様々なユーザ関数例 2 x max x と y の大きい方 y double 型の値を 2 つ受け取り、大きな方を返却値として返す関数 double max(double x, double y) { double tmp; if(x>=y) tmp = x; else tmp = y; return tmp; } 返却値は double 型、2 つの仮引数 x, y も double 型。 変数 tmp は、この関数の内部でのみ有効な局所変数。 どちらが大きいか判定して、値が大きな方を return 文で返す。

様々なユーザ関数例 2 関数呼出 double max(double, double); 関数 max のプロトタイプ宣言。 main() { double x, y, z; scanf(“%lf %lf”, &x, &y); z = max(x, y); printf(“%f\n”, z); } double max(double x, double y) double tmp; if(x>=y) tmp = x; else tmp = y; return tmp; 関数 max のプロトタイプ宣言。 引数の型をコンマで区切って宣言。 関数 max の呼び出し。実引数 x, y の値は、関数 max の仮引数 x, y にコピーされる。関数 max へ処理が移り、返却値を変数 z に代入。

様々な関数 値を返却しない(返却値がない)関数を void 関数と呼ぶ。 void graph(int n) { int i; for(i=0; i<n; i++) printf(“*”); printf(“\n”); } 返却値の型として void を指定。 引数として受け取った整数値分の * を出力して改行。 引数を持たない関数も定義できる。 void hello(void) { printf(“Hello!\n”); printf(“How are you?\n”); } 仮引数の宣言として void を指定。

様々な関数具体例 void graph(int); プロトタイプ宣言 main() { int score[10], i; /* 入力結果の視覚化 */ for(i=0; i<10; i++) graph(score[i]); } void graph(int n) int i; for(i=0; i<n; i++) printf(“*”); printf(“\n”); プロトタイプ宣言 関数呼出。 返却値はない。 main 文の変数 i と関数 graph 内の変数 i は別物であることに注意(ブロックスコープ)

問題 1 正の実数を受け取り、小数部分のみを取り出す関数を定義して、以下の動作をするプログラムを作れ。 ヒント:int 型の変数に double 型の値を代入すると小数点以下が 切り捨てられることを用いよ。 % ./a.out 正の実数を入力: 5.1234 小数部分は 0.1234 です。 % main 文はすでに完成している。関数 my_function を完成せよ。 double my_function(double); main() { double input, output; printf(“正の実数を入力:); scanf(“%lf”, &input); output = my_function(input); printf(“小数部分は %f です\n”, output); }

問題 2 成績(100点満点の整数値)を受け取り、秀、優、良、可、不可、を出力する 関数を定義して、以下の動作をするプログラムを作れ。 main 文の骨格はすでに完成している。 関数 hantei を定義せよ。 100~90 : 秀 89 ~ 80 : 優 79 ~ 70 : 良 69 ~ 60 : 可 59 ~ 0 : 不可 void hantei(int); main() { int score; printf(“成績を入力:”); scanf(“%d”, &score); hantei(score); } % ./a.out 成績を入力:90 貴方の成績は秀です。 % 関数 hantei は成績を引数として受け取り、上記の判定にしたがって、秀・優・良・可・不可を表示する。 (返却値無し)

問題 3 正の整数を受け取り、それが素数であれば 1 (int) を、素数でなければ 0 (int) を返却値として返す関数 prime を完成させよ。正の整数でなければ−1を返す様にする。 % ./a.out 正の整数を入力:13 13 は素数です % main 文の骨格部分はすでにでき上がっている。 int prime(int); main() { int i,r scanf(“%d”, &i); r = prime(i); if( r == 1 ) printf(“%d は素数です\n”, i); else if(r == 0) printf(“%d は素数ではない\n”, i); else printf(“%d は正の整数でありません。\n”, i); } 関数 prime は整数値の引数を受け取る。返却値は int 0 もしくは 1,-1 である。

問題 4 正の整数nを受け取り、1以上n未満のnの約数の和を求める関数 int yakusuu(int n) を定義せよ。これを使って、友愛数を求めるプログラムを作成せよ。 2 つの自然数について、 片方の約数(自分自身は 除く)の和が、他方の約数 (同じく自分自身は除く)の 和に等しくなるとき、これら 2 つの自然数は友愛数の 関係にあるという。 % ./a.out 220 の友愛数は 284 です。 1184 の友愛数は  1210 です。 2620 の友愛数は  2924 です。 5020 の友愛数は 5564 です。 ... % int yakusuu(int); main() { int i, j; for(i = 1; i < 100000; i++) { j = yakusuu(i); if (j > i && i == yakusuu(j)) printf(“%dの友愛数は%dです\n”, i、j); }

問題 5 z = f(x, y) = cos(x2 + y2)/(1+x2+y2) –4 ≤ x ≤ 4, –4 ≤ y ≤ 4 gnuplot 等の視覚化ツールを用いて次の関数をグラフに描け。 z = f(x, y) = cos(x2 + y2)/(1+x2+y2) –4 ≤ x ≤ 4, –4 ≤ y ≤ 4 2 次元平面上の点 (x, y) の高さが z = f(x, y) で与えられる 3 次元空間内の曲面。 2 つの引き数をもつ関数を自分で定義して次の形式で出力する。 % ./a.out -4.000000 -4.000000 0.025279 -4.000000 -3.900000 0.030390 -4.000000 -3.800000 0.017824 .... % ./a.out > data % gnuplot ... gnuplot > splot "data" gnuplot > quit % x, y, z の形式で出力(スペースで区切って出力) リダイレクションで計算結果をファイルへ書き込む。 gnuplot からデータファイルを読み込み視覚化する。

gnuplotによるグラフ描画 二次元グラフの描画 三次元グラフの描画 標本点の数を100に設定 % グラフを描く事が出来る。 % gnuplot gnuplot > plot "data” gnuplot >splot “ data2” gnuplot>set isosamples 100 gnuplot>splot [-4:4][-4:4]cos(x*x+y*y)/(1+x*x+y*y) gnuplot > quit   % 二次元グラフの描画 三次元グラフの描画 標本点の数を100に設定