このスライドの使い方

  • 画面下の「▶」で再生開始、「⏸」で一時停止

  • 画面右下の「>」で次頁へ、「<」で前頁へ

  • 青字下線の部分は、まとめプリントの穴埋め

  • 作業」のところでは、ファイルをダウンロードしてコンパイル・実行

第 8 章
「いろいろなプログラムを作ってみよう」

教科書 pp.227–253

§ 8-4「再帰的な関数」

(教 pp.240–243)

関数と型〜階乗値

(教 pp.240–243)

再帰 (recursion) — 関数の定義の中で自分自身を呼び出すこと。 一般に \(x\) の定義に \(x\) 自身を使用すること。

factorial(4)
  →  4 * factorial(3)
    →  4 * 3 * factorial(2)
      →  4 * 3 * 2 * factorial(1)
        →  4 * 3 * 2 * 1 * factorial(0)
          →  4 * 3 * 2 * 1 * 1

作業: List 8-7 を実行する

再帰(つづき)

  • “自分自身”と言っても、変数(仮引数や自動変数、 List 8-7 の factorial の場合 n)は別々に確保される
  • 繰返し(for, while)で簡単に実現できることを、 再帰で書くのは(C 言語の場合)良いこととはいえない
    • 階乗の例題プログラムは、あくまでも再帰を説明するためのものと考えること
    • もちろん、再帰を使わなければ簡単に書けないプログラムも今後たくさん出てくる
  • 再帰関数には、特別な文法も特別な実行規則も必要ない — あくまでも C 言語の普通の関数で、普通の実行規則に基づいて計算される

再帰(つづき)

作業: まとめのプリント Q 8.4.1 をやってみる

ハノイの塔WikipediA(再帰)

まとめのプリント

hanoi.c


#include <stdio.h>

void move(int n, int a, int b) {
    printf("ディスク%dを棒%dから棒%dへ\n", n, a, b);
}

void hanoi(int n, int a, int b, int c) { // n枚のディスクをaからbに移動する手順
    if (n > 0) {
        hanoi(n - 1, a, c, b);
        move(n, a, b);
        hanoi(n - 1, c, b, a); 
    }
}

int main(void) {
    int n;
    printf("円盤は何枚ですか? "); scanf("%d", &n);
    hanoi(n, 1, 2, 3);
    return 0;
}

作業: まとめのプリント Q 8.4.2 をやってみる

樹の描画(再帰)

まとめのプリント

tree.c


#include <stdio.h>
#include <math.h>

void drawTree(int d, double x, double y, double r, double t) {
    /* d       --- 再帰の深さ、 (x, y)  --- 枝の根元の座標、
       r       --- 枝の長さ、   t       --- 枝の伸びる向き(ラジアン)*/
    double r1;
    if (d == 0) return; /* 打切り */
    printf("%6.3f %6.3f %6.3f %6.3f\n", x, y, x + r * cos(t), y + r * sin(t));
    drawTree(d - 1, x + r  * cos(t), y + r  * sin(t), 0.5 * r, t);
    r1 = 0.5 * r;
    drawTree(d - 1, x + r1 * cos(t), y + r1 * sin(t), 0.5 * r, t + 3.1416 / 2);
    drawTree(d - 1, x + r1 * cos(t), y + r1 * sin(t), 0.5 * r, t - 3.1416 / 2);
}

int main(void) {
    drawTree(6, 128, 255, 128,  -3.1416 / 2);
    return 0;
}

作業: tree.cを実行する

樹の描画(つづき)

作業: まとめのプリント Q 8.4.3 をやってみる

§ 8-5「入出力と文字」

(教 pp.244–251)

getchar 関数と EOF

(教 p.244)

getchar は標準入力から文字を読み込んで返す関数

EOFgetchar などが、入力の終わり(End of File に由来)に達した場合に返す値をマクロで EOF と書く。(stdio.h に 定義されている。)
この値は、通常の文字とは区別される。

作業: List 8-8 を実行する

入力から出力へのコピー
〜数字のカウント

(教 pp.245–247)

教科書を読んでおく

リダイレクト

(教 p.247)

  • 標準入出力をファイルヘの入出力につなぎかえること
  • C 言語ではなく OS (Unix, MS-DOS など)の機能

コマンド < ファイル名 ファイルの内容をコマンドの標準入力に渡す
コマンド > ファイル名 コマンドの標準出力をファイルに書込む
コマンド >> ファイル名 コマンドの標準出力をファイルの最後に追加する形で書込む

文字コードと数字

(教 p.248)

  • C 言語では文字は、単にその文字に与えられたコード(整数値)で表す
  • 具体的な値は機種に依存する

ASCII での文字コードの抜粋:

文字10 進16 進
'0'480x30
'A'650x41
'a'970x61

文字コードと数字(つづき)

ただし、数字 '0', '1', '2', …, '9', については、文字コードもこの順に連続していることが保証されている

作業: List 8-11 を実行する

作業: まとめのプリント Q 8.5.1 をやってみる

拡張表記

(教 p.250)

  • \n」の他に、「\t」, 「\a」, 「\b」などいくつかの特殊文字を表す表記がある
  • 特に、バックスラッシュ(円記号)そのものを表すときには 「\\」と書く

第 8 章・終