トラック3・🔍人間がコンピュータになる訓練

総仕上げ——紙上プログラム実行

読む目安 約14分・ゴール:代入・分岐・繰り返しが混ざったプログラムを、最後まで自力でトレースできる

アプリでこのトピックを学ぶ(無料・登録不要)

このトピックの要点

第0部の締めくくりです。ここまでに学んだ道具を全部使って、少し長めのプログラムを紙の上だけで実行します。

題材

int sum = 0;
int i = 1;
while (i <= 5) {
    if (i % 2 == 0) {
        sum = sum + i;
    }
    i = i + 1;
}
printf("%d\n", sum);

% は割り算の余りを求める記号です。i % 2 == 0 は「i を2で割った余りが0」、つまり偶数かどうかを判定しています。文法はまだ習っていませんが、ここまでの説明で十分読めるはずです。

手順どおりにやる

  1. 表の列を決める(周 / 行 / i / sum / 条件 / 出力)
  2. 変数が作られた行から1行ずつ書く
  3. 条件は、変数を今の値に置き換えてから判定する
  4. 通らなかった行は書かない
  5. ループを抜けたあとの値まで、必ず追う

1周目の頭はこうなります。

周 | 行 | i | sum | 条件      | 出力
---+----+---+-----+-----------+-----
 ー|  1 | ー|  0  |           |
 ー|  2 | 1 |  0  |           |
 1 |  3 | 1 |  0  | 1<=5 真   |
 1 |  4 | 1 |  0  | 1%2==0 偽 |
 1 |  7 | 2 |  0  |           |

1周目は i が1(奇数)なので、5行目の sum = sum + i; は通りません。だから表にも書きません。続きはご自分の紙で最後まで進めてください。答え合わせは演習問題でどうぞ。

師範答えを見てから納得するのは、理解ではない。書いてから見よ。

確認したい3つの勘所

答えが出たら、そこで終わりにしない

表を最後まで書けたら、もう一段だけ確かめてください。この結果は、期待した結果か。

もし「2と4を足して6のはずが、表では6になった」なら合格です。もし違っていたら、表の中で最初におかしくなった行を探します。そこが原因の場所です。この紙の上の結果と実際の実行結果を突き合わせる作業が、そのままデバッグになります。

ビット表が書けたら、もう半分はプログラマだよ。あとは文法を覚えるだけ。

第0部を終えるあなたへ

ここまでで、次のことができるようになりました。

これは、C言語の文法を1つも知らない段階で身につけたものです。そして正直に言えば、ここから先で身につく文法よりも、この土台のほうが長く効きます。言語は移り変わりますが、分解する力とトレースする力は、どの言語でも、AIと組む時代でも減価しません。

次の第1部からは、いよいよC言語そのものに入ります。Hello, World! の1行を、あなたはもう「ただのおまじない」としてではなく、機械の中で何が起きるかを想像しながら読めるはずです。

アプリでこのトピックを学ぶ(無料・登録不要)

確認問題

確認問題 1

次のプログラムは、1から5までのうち偶数だけの合計(2 + 4 = 6)を求めるつもりで書いたものです。ところが実行すると 9 になりました。トレース表を書いて、原因のある箇所を選びましょう。

int sum = 0;
int i = 1;
while (i <= 5) {
    if (i % 2 == 1) {
        sum = sum + i;
    }
    i = i + 1;
}
  1. int sum = 0; の初期値
  2. if (i % 2 == 1) の条件
  3. sum = sum + i; の足し算
  4. i = i + 1; の更新
答えを見る

正解:B(if (i % 2 == 1) の条件)

i % 2 は「iを2で割った余り」なので、== 1 は奇数の判定になっています。結果として 1 + 3 + 5 = 9 が求まったわけです。偶数にしたいなら i % 2 == 0 と書きます。トレース表に条件の列を作れば、1周目(i = 1)でいきなり真になっている時点で気づけます。エラーが出ないのに答えが違うのが論理の誤りで、機械は何も教えてくれません。だからこそトレースが要ります。

確認問題 2

1から5までのうち偶数だけを合計するプログラムです。1周ごとの状態をトレースして、空欄を埋めましょう(条件の欄は「真」または「偽」)。

int sum = 0;
int i = 1;
while (i <= 5) {
    if (i % 2 == 0) {
        sum = sum + i;
    }
    i = i + 1;
}
周周の初めの ii % 2 == 0周の終わりの sum周の終わりの i
11偽02
22真23
33?24
44真?5
55偽6?
答えを見る

空欄の答え(上から順に):偽、6、6

3周目の i は3で、3を2で割った余りは1なので条件は偽——足し算の行は通らず、sum は2のままです。4周目は i が4で条件が真になり、sum は 2 + 4 = 6 になります。5周目は i が5で偽なので sum は6のまま、最後に i が1つ増えて6になります。この6が効いていて、次の判定 6 <= 5 が偽になるためループを抜けます。つまり抜けた時点の i は5ではなく6、出力される sum は 2 + 4 = 6 です。「最後に処理した値」と「抜けたときの値」が1つずれる点が、いちばんの勘所です。

「人間がコンピュータになる訓練」の目次

  1. トレース表とは——実行を目で見る道具
  2. 代入をトレースする
  3. 分岐をトレースする
  4. ループをトレースする
  5. バグを見つける思考法——仮説と検証
  6. ラバーダック・デバッグ
  7. エラーメッセージは敵ではない
  8. 総仕上げ——紙上プログラム実行

もっと先へ:ポインタ・メモリ・ファイル入出力・セキュアコーディングを含む全26トラックと、段位検定・模試のフルセットは完全版に収録しています。

完全版の販売ページは準備中です。

ほかのトラック

📚 姉妹教材:手を動かして覚える Linux 教材 — Linuxとインフラの仕組みを地図で学ぶ

Web版