コンテンツへスキップ
Topos Uranos

要約

このレッスンは、コースの第 8 単元、すなわち最後の単元の始まりであり、この単元はより大きなプログラムを扱う。単元の目的を説明する。もはや一つのファイルにも頭の中にも収まらないプログラムを編成し、検証し、デバッグすることである。単元の三つのレッスンと、それらを結ぶ糸を紹介する。その糸は、コースの最初のレッスンで開かれた輪(仕様を定める、作る、検証する)を閉じるものである。単元が前提とすること、すなわちコース全体を振り返る。単元が解決する問題を述べる。一つのファイルからなるプログラムが、テストに使ったデータでは動くのに、仕様の境界にある誤りについては黙っているという問題である。テストすることと証明することの違いを前もって示す。そして、最終プロジェクトと「C++ プログラミング II」のコースで、単元がどこへつながるかを示す。

学習目標

  1. 単元の内容の順序を説明し、各レッスンが次のレッスンに何をもたらすかを説明する。
  2. 例を一つ挙げて、関数の宣言と定義の違い、関数を規定する契約、そして複数のファイルを一つのプログラムに変える段階(コンパイルとリンク)を思い出す。
  3. 例を一つ挙げて、プログラムをいくつかのケースでテストすることと、許容されるすべての入力に対して正しいと証明することの違いを前もって知る。
  4. 単元とコースを終えたときに何ができるようになっているべきかを知り、それを「C++ プログラミング II」で学ぶことと区別する。

導入テスト

単元に取りかかる前に、出発点を測っておくとよい。このテストは採点しない。学習の方向づけのためのものである。最初の七問は、単元が前提とすること(宣言と定義、事前条件、第 6 単元のある関数の契約、リンカのメッセージ、二分探索のケース、トレース表、ベクターの範囲外の読み出し)を確かめる。続く三問は、レッスンの順に、単元の中心となる考え方を扱い、そこでは「まだわからない」が誠実な答えである。どの答えも要点を説明し、それを扱うレッスンを示す。同じ技能は、まとめのレッスンで再び測る。

導入テスト

単元を始める前に、自分の出発点を測りましょう。短い自己評価です。採点はされず、結果はあなたのブラウザーにだけ保存されます。

  1. 問 1前の単元からmain の前に書かれた int gcd(int a, int b); という行は何をするか。

  2. 問 2前の単元から関数 toBase(n, base) の事前条件は「n >= 0 かつ 2 <= base <= 10」である。それを保証しなければならないのは誰か。

  3. 問 3前の単元からレッスン 6.4 の関数 binarySearch(values, target) は、target の位置の一つを返し、見つからなければ values.size() を返す。その事前条件は何か。

  4. 問 4前の単元からあるプログラムはエラーなしにコンパイルできるが、実行ファイルをビルドすると undefined reference to `tetrahedral(int)' が出る。失敗したのはどの段階か。

  5. 問 5前の単元から次のケースの組のうち、二分探索を最もよく試すのはどれか。

  6. 問 6前の単元からint a{0}; int b{1}; for (int i{0}; i < 4; ++i) { const int t{a + b}; a = b; b = t; } の後で、a と b の値はいくつか。

  7. 問 7前の単元からstd::vector<int> v{1, 2}; std::println("{}", v[2]); は、コースのオプションでは停止するのに、サニタイザなしで -O2 だけを付けてコンパイルすると、任意の数を書き出すことがあるのはなぜか。

  8. 問 8インクルードガードをもつヘッダが、inline なしで double scale(double x) を(宣言するだけでなく)定義し、main.cpp と report.cpp がそのヘッダをインクルードしている。プログラムをビルドすると何が起こるか。

  9. 問 9ある関数が、念入りに選んだ五百個の自動テストを通る。何が言えるか。

  10. 問 10ループの中の total += k; の行にブレークポイントがあり、プログラムがそこで三度目に止まる。強調表示された行は何を示しているか。