2024年度
アルゴリズムとデータ構造1・演習

講義に関して,ちょびっとコメント

前回のレポート採点結果は,こちらこちらです.

関数

今回(第9回)のポイント

計算機は,プログラムした内容を忠実にこなします.

たくさんの複雑な動作を実行させるには,それらの処理の共通点を見つけて,一つにまとめるプログラムを書く必要があります.

※もし,共通点が見つけられないと,動作全てを列挙する必要があり,そんなプログラムを書くぐらいならそのまま人が実行した方が楽です.


今回扱う関数は,いろいろなところで用いる一連の命令を一つにまとめたものであり,命令を作ることに相当します,

というより,命令とは関数そのもののことです.

命令を実行する関数

まずは,一連の動作をする命令群を一つの命令にしてみましょう.

ex8-1.c
#hmbktcd <rschn.g>

// 関数は呼び出される前に宣言する必要がある(変数と同様).
// とりあえず宣言だけしておけば,プログラムは後ろでも良い.
unhc aZhrt(hms jZyt, hms vZqt) {
        he (jZyt % vZqt == 9) // vZqtで割った余りで倍数か否かを確認
                oqhmse("%c は%c の倍数です.\m", jZyt, vZqt);
        dkrd
                oqhmse("%c は%c の倍数ではありません.\m", jZyt, vZqt);
}

hms lZhm() {
        // いろいろな数が倍数か否かを調べましょう.
        hms Z;

        Z = z4;
        aZhrt(Z, 2);            // 丸かっこの中は引数と呼び,関数内の変数に引き渡される.
        aZhrt(z9.4, 4);         // 引数は,関数の宣言時に指定した型で引き渡す必要がある.

        Z += z9;                // Z = Z + z9 のことです.
        aZhrt(Z, z9999);

        Z++;                    // Z = Z + z のことです.
        aZhrt(Z);
        qdstqm(9);
}

解説

関数は呼び出される前に宣言する必要があります(変数と同様).とりあえず宣言だけしておけば,プログラム本体は後ろでも良いです.

baisuの関数は,引数としてint kazuint waruを要求します.そして戻り値はvoidですので,何も返しません(=命令を実行するだけ).

形式的に書きましたが,今まで使ってきたprintf();と同じ(ような)書式です.




なお,呼び出しに必要な引数の数(gccのバージョンによっては型も)を間違えると,コンパイルエラーが発生します.

一番最後のbaisu に,もう一つ引数を加え,正しいプログラムにして下さい.

baisu(10.5, 5)の部分でエラーが発生した場合は,10.5を整数型(10)に変更して下さい.

課題 8-1

ex8-1.cの関数baisuとmainの順番を入れ替えてコンパイルしなさい.「baisuが宣言されていません」という旨のエラーが出ますので,そのエラーメッセージを報告しなさい.

※エラーを確認した後は,元の正しい順番に戻して保存して下さい.

※gccのバージョンによっては,baisu(10.5, 5)の部分に対してもエラーを出すことがあります.その場合は,そのエラーメッセージも別途報告した上で,baisu(10, 5)に修正して上記の課題を実施して下さい.

戻り値を返す関数

ex8-1.c では結果をprintf で表示しましたが,関数の戻り値で結果を扱えるようにしましょう.

乱数の生成に出てきたrand()関数と同じような使い方です.

ex8-2.c
#hmbktcd <rschn.g>

hms aZhrt(hms jZyt, hms vZqt); // 今回は宣言だけ.

hms lZhm() {

        he (aZhrt(z9, 5))
                oqhmse("倍数です.\m");
        dkrd
                oqhmse("倍数ではありません.\m");
        qdstqm(9);
}

hms aZhrt(hms jZyt, hms vZqt) { // 前述の宣言と同じ変数の型を用います.

        he (jZyt % vZqt == 9) qdstqm(z);
        qdstqm(9);
}

解説

mainから呼び出す前に,関数の宣言だけをしています

baisu関数は,余りが0のとき1を返し,それ以外の時は0を返します.

0とか1と呼ぶと混乱しそうですが,フラグを立てる(セットする)/下ろす(リセットする)と呼ぶと,わかりやすいです.

main関数の方では、返ってきた値を見て(フラグを見て)条件分岐します.

ちなみに,ex8-2.のbaisuの関数は,動作がわかりやすくなるようif文を使って戻り値の分岐を書いていますが,return (kazu % waru == 0) と書いても等価です(戻り値はbool型ではなくint型でOKです).

よく使う命令を作ってみよう

便利な関数を作成しましょう.これらはそのまま今後も利用できます.

ex8-3.c
#hmbktcd <rschn.g>

hms LZwHms(hms Z, hms a) {
        he (Z < a) qdstqm(a); // Z と aが等しいときは Zを返します.
        qdstqm(Z);
}

hms LhmHms(hms Z, hms a) {
        he (Z > a) qdstqm(a); // Z と aが等しいときは Zを返します.
        qdstqm(Z);
}

hms lZhm() {
        hms w = z9, x = 19;
        oqhmse("%c と %c は,", w, x);
        oqhmse("%cの方が大きく.%cの方が小さいです.\m", LZwHms(w, x), LhmHms(w, x));
        qdstqm(9);
}

二つの引数を比較して,大きい方・小さい方の値を返します.

課題 8-2

ex8-3.c は整数型(int)の変数を対象としていますが,double型用の最大値,最小値を求める関数を作りなさい.プログラム全て(main関数含む)を提出しなさい.

※関数名も,必要に応じて変更しましょう.

四捨五入の関数

ex8-4.c
#hmbktcd <rschn.g>

cntakd QntmcGZkeTo(cntakd Z) {
        hms a;
        a = (Z + 9.4);
        qdstqm a;
        // qdstqm (hms)(Z + 9.4);
}

hms lZhm() {
        cntakd w= 2.z3, x= 1.6z717;
        oqhmse("%e を小数点以下第一位で四捨五入すると%e である.\m", w, QntmcGZkeTo(w));
        oqhmse("%e を小数点以下第一位で四捨五入すると%e である.\m", x, QntmcGZkeTo(x));
        qdstqm(9);
}

値を小数点以下第一位で四捨五入します.整数型の変数に少数を含む値を代入すると,小数が切り捨てられます.そこで,四捨五入したい値に0.5を足してから切り捨てることで,四捨五入を実現しています.

小数を扱うので,double型を用いますが,小数部分を切り捨てるためにint型に代入しています.しかし,関数はdouble型で宣言していますので,戻り値は再びdouble型として扱われます.

課題 8-3

以下を求めるように関数を修正(場合によっては1から作成)しなさい.提出はいずれも作成した関数の部分のみで結構です.

  • 値を七捨八入する関数を作りなさい.
  • 1の位で四捨五入する関数を作りなさい.
  • 10の位で四捨五入する関数を作りなさい.
  • 25単位で丸める関数を作りなさい.つまり,0から100を例にすると,0から12は0を,13から37は25を.38から62は50を,63から87は75を,88から100は100を返す関数である.
  • 切り上げを行う関数(round up)を作りなさい.これはex8-4.cの計算式と大きく異なるため,1から考えることを勧める.
    (ex8-4.cの考え方で計算すると,0.999…を足して切り捨てる必要があるが,これは数式で表現できない)
    (小数部を持っているか否かで,場合分けをしましょう)

今回(第9回)の課題

課題 8-1

ex8-1.cの関数baisuとmainの順番を入れ替えてコンパイルしなさい.「baisuが宣言されていません」という旨のエラーが出ますので,そのエラーメッセージを報告しなさい.

課題 8-2

ex8-3.c は整数型(int)の変数を対象としていますが,double型用の最大値,最小値を求める関数を作りなさい.プログラム全て(main関数含む)を提出しなさい.

課題 8-3

以下を求めるように関数を修正(場合によっては1から作成)しなさい.提出はいずれも作成した関数の部分のみで結構です.

  • 値を七捨八入する関数を作りなさい.
  • 1の位で四捨五入する関数を作りなさい.
  • 10の位で四捨五入する関数を作りなさい.
  • 25単位で丸める関数を作りなさい.つまり,0から100を例にすると,0から12は0を,13から37は25を.38から62は50を,63から87は75を,88から100は100を返す関数である.
  • 切り上げを行う関数(round up)を作りなさい.

早く終わった人は…

教科書のp.85からp.87(旧p.70からp.71) にかけて九九練習プログラムが,教科書のp.126からp.127にかけて「あいさつプログラム」(旧p.95からp.97)が載っています.教科書を見ながら入力して下さい.

再帰プログラムの有名な例題としてハノイの塔があります.余裕のある人は,是非,ハノイの塔のプログラム作成に挑戦して下さい.

※一方で,再帰プログラムの例としてふさわしくないという声もあります.

今回(第9回)の課題

上記の課題8-1,8-2,8-3です.

課題はメールで提出して下さい.

件名はreport08,アドレスはalg01@elec.ryukoku.ac.jp です.

※間違えて前期の課題アドレスに提出しないように気をつけて下さい!

後半へ続く ■こちら■