計算機言語 I 第 7 回 関数
この資料
: http://www.math.u-ryukyu.ac.jp/~suga/gengo/2020-1/07.pdf
レポートへのツッコミ
みなさんが提出したレポートのプログラムは
,
複雑に考えすぎです.
様々な応用のために一般的なプログラ ムを書くということも重要ですが,
ある目的を達成するためだけに,
できる限り簡潔なプログラムを書くこと も重要です.
どちらを選ぶかは,
局面によって違いますので,
「臨機応変」な態度を養ってください.
• report 6-2:
置換の符号を出力するには, 1
で初期化した変数(
例えば, sign)
を用意し,
バブルソートで互換が起こる度に
− 1
を掛けていけばいいのです.
ソートが終わると,
単位元になっているわけですが,
上の操作で得た値が符号です.
即ち,
交換の回数を数えるの必要はありません.
• report 6-3:
上と同様に,
前回の資料で示したバブルソートのプログラムで,
交換が起こった時の場所(
配列の添字が0
から始まっているので,
場所の値は,
配列の添字に1
を加えたもの)
を順に出力してい くと,
置換の逆元を隣接互換の積での表示が得られます.
教科書 6 章の補足
関数については
,
教科書に従って解説します.
教科書に書かれていない事を補足します. 6.1
節関数の返り値
(
教科書では型,
英語ではreturn value)
として使えるのは,
これまでに出てきた, (unsigned, signed) char, int, float, double
とこれからの講義で出てくる
,
ポインタ型,
構造体,
共用体で,
配列を関数の返り値にはできません.
関数を利用する最も大きな理由は
,
「プログラムを適当な大きさに分割して書く」です.
処理の長さが100
行 を超えるくらいから,
その処理を人間が追うのは難しくなることが知られています.
そこで,
関数を利用してプ ログラムを小さく分割して書いていく様にします.
6.2
節実際の関数の記述の際の関数の引数を「仮引数」と言います
.
仮引数で用いられている変数名は,
その関数 内だけで使える「局所変数(
ローカル変数, 6.3
節)
」です.
教科書
, p. 85
は正確でないところがあります.
関数の使い方なのですが, C
の正確な仕様は,
C
では,
関数呼び出しをする前にその関数の素性をコンパイラに知らせなければならない.
1
です
.
上のことを実現するには,
次のいずれかの方法をとる必要があります. 1.
その関数呼び出しの前にその関数自体を記述してしまう.
2.
関数呼び出しの前に,
その関数のプロトタイプ宣言を記述する(
教科書p. 86).
教科書には
, 1.
の方法が書いてありませんが,
そのようなプログラムを書いても大丈夫です.
コンパイラは 関数の素性(
返り値,
引数の型)
を用いることにより,
機械語を効率よく作成できますが,
これがないと,
どのよ うな機械語を作り出して良いかがわかりません.
そのために,
上のような仕様があります.
6. 3
節, 6. 4
節, 6. 5
節情報科学演習や計算機概論で述べたように
,
コンピュータの処理は次をやっているわけです. 1.
入力を受け取とる.
2.
それに対する処理をする. 3.
結果を出力C
でのプログラム作成は,
上のことを関数に分割して実行します.
それぞれの関数が,
引数として入力を受 け取り,
返り値で結果を返すわけです.
これらの関数の集まりとして,
一つのプログラムが構成されます(
教科 書p. 83
後半部分の図).
上の図からもわかるように
, C
のプログラムでは,
入力を次々と関数に渡して処理をし,
最終的な出力を得る ようになります.
この際に,
各関数へのデータの受け渡しと関数内での処理が,
どのように実装されるかを解説 してある節です.
基本的な考え方は
,
次です.
値を変更する場所は
,
できる限り狭い範囲に限定する.
ある値が
,
プログラムの多数の場所から変更できるようになっていると,
プログラムに間違い(
バグ)
がある時,
バグの修正が大変になるのです.
バグの修正は,
値の変更が想定通り実行されているかを追うことによってな されることが多く,
「値を追う」のを簡単にするには,
その値が変化する場所を狭くするのが,
もっとも単純な 解決法だからです.
「値渡し」や「局所変数」はそのための仕組みです.
ただ
,
値渡しだけでプログラムを全て書くのも大変なので,
参照渡しの方法も用意してあるのです.
教科書で は,
ポインタ(
次週講義予定)
を利用した参照渡しが解説されていますが,
これ以外にも,
外部変数や大域変数 を用いた参照渡しが可能です.
2
6. 7
節再帰は
,
関数内で自分自身を呼び出すことです.
計算機概論
I
のmaple
の講義の回で,
再帰の話を1
度しました.
その際にも述べたことですが,
再帰の利点,
欠点は次になります.
•
プログラムの記述が簡潔で分かりやすく(
読みやすく)
なる.
•
関数呼び出しの度にスタック領域と呼ばれるメモリを消費するので,
処理によってはメモリが足りなく なる.
•
関数呼び出しという動作が数多く起こるため,
プログラムの動作が遅くなる(
今回のレポート問題).
今回のレポート問題にある様に
,
再帰を繰り返し処理で書けるのであれば,
実行時間を考えると,
繰り返し処 理で記述方が望ましいのがほとんどです.
ただし
,
教科書のHanoi
の塔の様に再帰でしか書けないような処理もありますし,
繰り返し処理に変換するのが大変な場合もあります
.
後者の例としては,
プログラム言語処理系の作成が良く取り上げられます.
3
レポート問題
締切
: 7
月6
日(
月) 10:00(JST)
1.
次の様なプログラムを作れ. (
件名: gengo2020-1 report 7-1)
• Heron
の公式により3
角形の3
辺からその面積を計算する関数heron
を書く関数
heron
では, 3
つのdouble
型の引数(3
辺の値)
を取り,
面積の値をdouble
型で返す.
ただし, 3
つの引数の値が3
角形を作らないときには, 0
以下の値を返す(
値は,
何でも良い).
• main
関数では, 3
つのdouble
を標準入力から読み取り,
関数heron
を利用して,
それらが3
角形 を作ればその面積,
作らなければ「入力した3
数は3
角形を作りません」を出力する.
Heron
の公式の特性をうまく利用したプログラムを書いてください.
2. a
0= a
1= 1, a
n+1= a
n+ a
n−1, (n ≥ 1)
で定義されるFibonacci(
フィボナッチ)
の数列について,
次 の2
つのプログラムを書き,
そのプログラムを提出するとともに,
処理に掛かったおよその時間をレ ポートせよ. (
一瞬とか,
何分程度かかったかとか.)
ただし,
どちらの関数も, unsigned long long
型(
符号無し64bit
整数)
の変数を利用して, a
50の正しい値が表示できるようにすること. printf
でのunsigned long long
の出力の指定方法は, %llu. (man 3 printf
を参照).
•
繰り返し(for
でもwhile
でも良い)
を用いて,
自然数n
の入力に対して, a
n を出力する関数fibonacci(int n)
を書き, main()
では, a
50を出力するプログラム.
件名
: gengo2020-1 report 7-2.
•
再帰を利用して,
自然数n
の入力に対して, a
nを出力する関数fibonacci(int n)
を書き, main()
では, a
50を出力するプログラム.
件名