第7回 関数とプログラム構造(1)

第7回 関数とプログラム構造(1)
関数について
 通用範囲(スコープ)
 外部変数

関数について

関数とは?
ある入力パラメータ(引数という)を受け取り、
 計算処理を行い、
 ある出力を返す(返り値、戻り地という)

入力
出力
関数 f
関数化すると?
関数化しなくてもプログラムを作成できる
 何故、関数化するのか?

モジュール化(部品化)




main関数に全ての処理を記述するのは、プログラ
ムが長くなり、見ずらい
頻繁に行われる共通の処理を関数化することによっ
て、プログラムの再利用性、柔軟性を高める → モ
ジュール化(部品化)
関数化によってプログラムが短くなり、見やすくなる
関数化することによる各処理の結合がシンプルにな
り、プログラム中の誤りが出にくくなる。
関数の形式





あるパラメータを入力として与えて、なんらかの処理を行わ
せ、結果を出力する
入力パラメータを、引数と呼ぶ
結果として返される値を、戻り値(返り値、返戻値)と呼ぶ
return-type function-name(parameter declarations, if
any){
declarations;
statements;
return 文;
}
累乗を計算する関数power の作成
 int
power (x,y) ... x ^ y (xのy乗)を計算して結果を返す
return 文 – 値を返す-

return 文
return 式;
関数が値を返すときに返す値をreturn の式
に示す
 返す型は、関数のプロトタイプ宣言で宣言し
たデータ型となる

通用範囲(スコープ)

変数は、それぞれ宣言した場所によって通用
範囲(スコープ)が定まる
ファイル中の関数の外側の宣言部 →
ファイル内からはアクセス可能
関数のはじめの宣言部 → 局所変数
(関数内) : その関数内からはアクセス可
能
外部変数

外部変数: グローバル変数を任意の関数の外
側で定義したもの。
 通用範囲(スコープ)が広域にわたる…どの関数から
もアクセス可能
 変数のライフタイム(生存時間)が永続的である


cf). 自動変数
外部変数は、広域的にアクセスできるため、関数
間のデータのやりとりとして引数、返り値の代わ
りになりうる
 ただし使用する場合は、データの結合が密・複雑化す
ることに注意する(バグの温床)
外部変数の宣言と定義


宣言... 実体は作成されない(記憶領域への割り当
てなし)
extern という修飾子をつける。ファイル外で定義さ
れた外部変数の宣言。プログラムで複数あってよい。
定義 ... 実体が作成される(記憶領域への割り当て
あり)
局所変数の宣言と同じように記述するが、関数の外
側に記述する。プログラム中にただ一つのみ。
簡易電卓プログラムの作成

ユーザの数式入力に対して、答えを返す電卓プロ
グラム


例) 入力 => ( 1 – 2) *( 4 + 5 ) = ↵
答え: -9
プログラム作成の手順
1.
2.
3.
4.
逆ポーランド記法に直す
数字(オペランド)をスタックに積む
オペレータがきたら、オペランドスタックから2つオペラ
ンドを取り出し、演算をしてまた、オペランドスタックに積
む
オペランドスタックが空になるまで3.の処理を繰り返す。
逆ポーランド記法


通常の数式表現は中置記法といい、オペランドの間にオペ
レータを挿入している
逆ポーランド記法: オペレータはオペランドの後に置く


構文木を作成し、後順探索の順番で記述したもの
実際には、
オペランドはそのまま書く

オペレータ -、+の場合は、次のオペランドが*、/でない限り置ける

オペレータ *、/ の場合は次の語句がオペランドであれば置けるが、
括弧である場合は、対応する括弧が閉じないと置けない。

括弧は無視する
※ 括弧とイコールもオペレータの一つであると考える


(1 – 2 ) *( 3 – 4 ) は 1 2 – 3 4-*となる
スタックを利用した逆ポーランド記法
による演算


スタック … 上にのみ出入り口のある入れ物。先
入れ後出しQueue(待ち行例)。
手順
 もし、とってきたものがオペランドならば、オペランドスタッ
クに積み上げる(PUSHという)
 そうでなくて、とってきたものがオペレータならば、
 オペランドスタックから2つオペランドを上から取り出す(こ
れをPOPという)
 取り出した2つのオペランドに、オペレータの演算を行う
 演算結果をオペランドスタックの上に入れる(これをPUSH
という)