コード読解演習 Step 1【初級】:手続き型データフローの追跡

単一ファイル・手続き型コードから「状態変数」と「メインループの実行順序」を抜き出す

何百行もある手続き型ソースコードを前にしても動じない!変数がどこで初期化され、ループ内でどう書き換わり、どこへ出力されるのか——「状態変数のライフサイクル」と「実行順序」をプロの眼力でトレースする基礎体力を養成します。


1.1 初級読解の極意:上から下へ読むな!「変数表」を頭に作れ

手続き型コードを1行目から小説のように読んではいけません。最初に「何が状態(データ)で、何が更新処理か」を分離して捉えます。

🐧 ペンギン先輩
シロクマ先生!先輩から「このレガシーな保守コード、どんな挙動してるか読んで仕様書にまとめて」って言われたんですけど、1つの `main.cpp` に変数がいっぱいあって、上から順に読んでたら途中で何が何だか分からなくなって頭がオーバーヒートしました…!
🐻‍❄️ シロクマ先生
ふぉふぉふぉ、典型的な新人のトラップじゃな!手続き型プログラムは「小説」ではなく「工場のベルトコンベア」じゃ。1行目から流し読みするのではなく、**【① 状態変数(保管庫)をリストアップ】→【② ループ(加工工程)での更新式を追跡】→【③ 終了・出力条件】**の3ステップで解読するのじゃ!

### 手続き型コード読解の「3ステップ・スキャン法」

1. **ステップ1:状態変数(State Variables)の洗い出し**:
- 関数の先頭で宣言されている変数は何か?
- どれが「座標(X, Y)」で、どれが「タイマー/カウンタ」、どれが「フラグ(bool)」か?
2. **ステップ2:メインループの「フレーム更新周期」の特定**:
- `while` や `for` の条件式は何か?(何が起きたらループを抜けるか?)
- 1周ごとに値が増減する変数はどれか?(時間の経過を表す変数)
3. **ステップ3:入力と分岐(If文)による「状態遷移」の図式化**:
- ユーザー入力や特定条件で、どの変数がどう書き換わるか?
💡 このセクションの重要ポイント
  • 変数を「役割別」に脳内分類する: 位置データ、進行カウンタ、状態フラグ(生存/死亡など)に変数を分類するだけで、読むべき行数が1/3に圧縮されます。

1.2 演習コード:宇宙探査ポッドの手続き型シミュレータ

以下のC++コードを読み解き、ポッドの燃料消費と高度変化のデータフローを追跡してください。

📄 lander_procedural.cpp
#include <iostream>

// 月面探査機の手続き型シミュレーション
int main() {
    // --- 【状態変数グループ】 ---
    double altitude = 100.0; // 高度 (m)
    double velocity = 0.0;    // 降下速度 (m/s) 正値で降下
    double fuel = 50.0;       // 残り燃料 (L)
    const double gravity = 1.62; // 月面重力加速度
    int timeSeconds = 0;      // 経過時間
    bool landed = false;

    // --- 【シミュレーション・メインループ】 ---
    while (!landed) {
        timeSeconds++;
        double thrust = 0.0; // この秒の噴射推力

        // 簡易オートパイロット判断ロジック
        if (altitude < 30.0 && fuel >= 5.0) {
            thrust = 3.0; // 逆噴射で減速
            fuel -= 5.0;
        } else if (altitude < 60.0 && fuel >= 2.0) {
            thrust = 1.8;
            fuel -= 2.0;
        }

        // 物理計算(データフロー:重力と推力から速度と高度を更新)
        velocity += (gravity - thrust);
        altitude -= velocity;

        // 接地判定
        if (altitude <= 0.0) {
            altitude = 0.0;
            landed = true;
        }

        std::cout << "[T=" << timeSeconds << "s] 高度: " << altitude 
                  << "m, 速度: " << velocity << "m/s, 燃料: " << fuel << "L\n";

        // 安全装置:燃料切れかつ速度超過なら暴走防止で緊急中断
        if (fuel <= 0.0 && velocity > 15.0) {
            std::cout << ">>> 警告:燃料枯渇!墜落コースに入りました\n";
            break;
        }
    }

    // --- 【結果判定】 ---
    if (velocity <= 3.0) {
        std::cout << "=== 軟着陸成功!探査ポッドは無事です ===\n";
    } else {
        std::cout << "=== 衝撃大!着陸脚が破損しました (着地速度: " << velocity << "m/s) ===\n";
    }
    return 0;
}
💡 このセクションの重要ポイント
  • 一時変数(スコープ内)と蓄積変数(スコープ外)を見分ける: 毎フレーム上書きされる使い捨て変数と、前のフレームの結果を蓄積する変数を区別することが読解の第一歩です。

📝 理解度チェッククイズ

Q1. 演習コードにおいて、ループを跨いで前のターンの計算結果を記憶し続ける「永続状態変数」はどれでしょう?
  • 1. thrust のみ
  • 2. altitude, velocity, fuel, timeSeconds
  • 3. gravity のみ
  • 4. timeSeconds と thrust のみ
正解と解説を見る
正解:altitude, velocity, fuel, timeSeconds
正解です!altitude, velocity, fuel, timeSeconds は while ループの外側で宣言されており、各反復での変化が累積していきます。一方 thrust はループ内で宣言されているため毎反復リセットされる一時変数です。
Q2. 高度(altitude)が 25.0m で、残り燃料(fuel)が 10.0L のとき、オートパイロットが選択する逆噴射推力(thrust)と燃料消費量はどれでしょう?
  • 1. thrust = 0.0、燃料消費 0.0L
  • 2. thrust = 1.8、燃料消費 2.0L
  • 3. thrust = 3.0、燃料消費 5.0L
  • 4. thrust = 5.0、燃料消費 3.0L
正解と解説を見る
正解:thrust = 3.0、燃料消費 5.0L
正解です!`if (altitude < 30.0 && fuel >= 5.0)` の第1条件に合致するため、thrust = 3.0 が代入され、燃料が 5.0L 消費されます。
Q3. このシミュレーションで「軟着陸成功」と判定されるための絶対条件は何でしょう?
  • 1. 残り燃料が 0L であること
  • 2. 経過時間(timeSeconds)が 10秒以内であること
  • 3. 高度が 0.0m に達した時点の降下速度(velocity)が 3.0 m/s 以下であること
  • 4. thrust が一度も 3.0 にならなかったこと
正解と解説を見る
正解:高度が 0.0m に達した時点の降下速度(velocity)が 3.0 m/s 以下であること
正解です!接地判定後、ループを抜けた先の `if (velocity <= 3.0)` によって軟着陸の成否が判定されます。
Q4. このような手続き型コードを保守する際、最も発生しやすい典型的なバグ(落とし穴)は何でしょう?
  • 1. クラスが多すぎてファイルが見つからないこと
  • 2. 変数の値がどこで誰によって書き換えられたか追跡が難しく、計算順序を1行入れ替えただけで挙動が激変すること
  • 3. vtableの仮想関数呼び出しオーバーヘッドで速度が低下すること
  • 4. テンプレートのコンパイルエラーが長すぎること
正解と解説を見る
正解:変数の値がどこで誰によって書き換えられたか追跡が難しく、計算順序を1行入れ替えただけで挙動が激変すること
正解です!手続き型コードはデータが広域スコープで共有されがちなため、代入のタイミングや順序への依存度が高く、修正時の予期せぬ副作用(バグ)を生みやすいのが弱点です。

🐻‍❄️ シロクマC++ラボ インタラクティブ学習システム

ブラウザでJavaScriptを有効にすると、ブラウザ内インベーダーゲームエミュレータ、メモリマップ可視化、UMLクラス図、対話型解説、理解度クイズが起動します。

インタラクティブ学習を開始する →