◎第9回 手続きと関数
◇下へ・一覧へ
○テキスト
5章(5.1)
手続き(procedure):段階的詳細化をプログラミング言語上で記述する機構
ある一連の操作を、分離して記述したもの
◇下へ・上へ
○「手続き」を使う利点
・区切りのいいところをまとめて、別に記述する
プログラムが見やすくなる
・大きな(複雑な)処理を分割してデバッグなどをしやすくする
→ モジュール化
・似かよった操作がしばしば行なわれるとき
同じプログラムを何度も書かないですむ
○手続きの種類
メインルーチン(main routine):プログラムを起動したとき最初に実行される手続き
サブルーチン(subroutine):あるまとまった処理(「値」を返さない)をする手続き
関数(function):結果として1つの「値」を返す、サブルーチンの変種
返す値の「型」に注意が必要
◇下へ・上へ
○手続き中のパラメタと変数の扱い
・パラメタ(引数):手続き間で渡されるデータ(変数)
手順は同じだが「対象」は異なる
仮パラメタ(仮引数 formal parameter)・・・サブルーチン、関数内での
操作記述のための仮の名前
実パラメタ(実引数 real parameter)・・・サブルーチン、関数を呼び出すときに
指定する実際の操作対象
・変数の扱い
局所変数(local variable):あるサブルーチン、関数内のみで使われる変数
大域変数(global variable):全ての実行単位で使うことのできる変数
(これまで出てきた変数はすべてlocal変数)
・データの受け渡し方法
値パラメタ・・・値渡し:変数(式)の値を渡す(コピーを渡す)
手続き内で仮パラメタを変更しても、
呼出側の実パラメタは変わらない
変数パラメタ・・変数渡し:変数のアドレスを渡す
手続き内で仮パラメタを変更すると、
呼出側の実パラメタも変わる
<言語による違い>
Fortran 変数渡し。呼ばれたルーチンが元の引数にアクセスできる
Pascal 指定可能(var パラメタ)
C 値渡し。値しか受け渡すことができない
変数渡しをしたければ、ポインタ変数を使う
◇下へ・上へ
○C言語における関数
Pascalの手続きあるいは関数、Fortranのサブルーチンあるいは関数を、
C言語ではまとめて「関数」と呼ぶ
(例)最初に実行される関数 main
あらかじめ用意されている関数 sqrt( )、sin( )、cos( )
あらかじめる用意されている「サブルーチン的関数」 printf( )、scanf( )
・自分で「関数」を定義できる
実はすでにmainという名の関数を定義している。適当な名前をつければよい
あらかじめ用意されている関数と同じ名前は使えない(使える場合もある)
・関数の作成法
1. まとまった処理を切り出して独立した関数にする
a) その部分を切り出して、{ }でくくってブロックにする
b) 関数名を考え、a)のブロックを関数定義する
c) 元の部分に関数呼び出しを書く
d) 処理のために必要な変数定義部分をブロックに入れる
2. 関数と呼び出し側のデータの受け渡しの方法を決める
戻す値はいくつか(0 or 1 or 複数)
3. 元の関数(呼び出し側)で、不要な変数宣言を取り除く
分離した処理と、呼び出し側に残す処理に共通の変数に注意
◇下へ・上へ
・関数の定義と使用法
(例)二つのデータの和の平方根を求める関数の一部
関数が返す値の型 関数名(仮パラメタリスト) double kansuu(x, y)
仮パラメタの型宣言; double x, y;
{ ブロック {
local変数zの型宣言; double z;
関数の本体 z=sqrt(x+y);
計算した値をreturn文でmainに返す(cへ) return z;
} }
関数kansuuを呼び出す関数main main()
{ {
local変数a,b,cの型宣言 double a, b, c;
: :
関数名(実パラメタリスト) c=kansuu(a, b);
: :
} }
◇下へ・上へ
(関数の詳細)
◇下へ・上へ
・Cで値を返すとき
1. 「関数」なので関数の値として返す ……1つだけ
2. パラメタとして変数のアドレスを渡す ……いくつでも可
ポインタ変数 ……アドレス(実際のメモリ上の位置)を操作するために作った変数
呼び出すほう:変数のアドレス(ポインタ)を渡す
実パラメタ……「& 変数」と書く
呼ばれたほう:パラメタがポインタであることを宣言、
ポインタを通して実際の変数を参照
仮パラメタ……変数名の先頭に*をつける
仮パラメタの宣言例
値パラメタ int a; 型 仮パラメタ名
(例1) a
変数パラメタ int *a; 型 *仮パラメタ名
(例2) *a
配列変数パラメタ int a[ ]; (または int *a) 配列=ポインタ変数
(例3) a[i]
◇下へ・上へ
○演習9
9.1 次のプログラムで、
#include <math.h>
をなくした時の動作を調べよ。
#include <stdio.h>
#include <math.h>
main()
{
double x;
scanf("%lf", &x );
printf("exp(%f)=%f\n", x, exp(x));
}
9.2 次の c プログラムの指定した各処理や条件判断が実行される順番を考えよ。
また、このプログラムは、
% c-order ファイル名
で実行した部分が表示されるので確認せよ。
c-order4.c
9.3 第7回演習の数値積分プログラム(integral.c)に
おいて、処理部分を「積分値を値として返す関数」として切り出し、
全体を書き直して、コンパイル・実行し動作を確認せよ。
( 解答例(integral-f.c) )
◇一覧へ・上へ
○レポート課題9 (解答)
以下の課題のプログラムリストおよび実行結果を提出せよ。
9.1 第4回課題4.2の整列プログラム(seiretu0.c)において、
整列部分,データ入力,データ出力を関数として書き直し、
コンパイル・実行して動作を確認せよ。
(今回の総和の例が参考になるであろう)
(ヒント:seiretu10.c)
9.2 2分法のプログラム nibun2.cにおいて、
処理部分を「解を値として返す関数」として切り出し、
全体を書き直して、コンパイル・実行し動作を確認せよ。
epsilonの入力には、1e-6(1*10の-6乗)のような書き方もできる。
(今回の総和の例や演習3の解答例が参考になるであろう)
2分法の説明