制御構文(条件分岐とループ)
プログラムの「実行する順番」を操る仕組み。上から順に・条件で枝分かれ・同じ処理を繰り返す、の3つを組み合わせてロジックを組み立てる。
- 1.制御構文は実行の流れを操る3要素=順次・分岐・反復の組み合わせがすべて。
- 2.条件は最終的に真偽値(true/false)に評価される。break で抜け、continue で次の周回へ飛ぶ。
- 3.早期return とガード節でネストを浅く保つと、読みやすくバグの少ないコードになる。
仕組み:3つの基本要素
コードは何もしなければ上から下へ1行ずつ実行されます(順次)。制御構文は、この流れに「枝分かれ」と「繰り返し」を加えるためのキーワードです。
| 要素 | やること | 代表的なキーワード |
|---|---|---|
| 順次 | 書いた順に上から実行する | (特別な構文なし) |
| 分岐 | 条件によって実行する処理を選ぶ | if / else / switch |
| 反復 | 条件が満たされる間、繰り返す | for / while / foreach |
構造化プログラミングの基本定理として、この3つさえあればどんなアルゴリズムも書けることが知られています(Böhm–Jacopini の定理)。goto のような「好きな場所へ飛ぶ」命令が不要なのは、このためです。
真偽値と条件
分岐や反復の「条件」は、最終的に真偽値(boolean)= true か false のどちらかに評価されます。
const age = 20;
if (age >= 18) { // age >= 18 は true に評価される
console.log("成人");
} else {
console.log("未成年");
}
多くの言語では、boolean 以外の値も条件に書けてしまいます。JavaScript なら 0・""(空文字)・null・undefined・NaN は「偽っぽい値(falsy)」として扱われます。if (list.length) で「空でないか」を判定できて便利な反面、if (count) は「count が 0 のとき」も偽になり、意図しない挙動の温床に。曖昧さを避けるなら if (count > 0) のように明示的に比較しましょう。
分岐:if / else と switch
枝が2〜3本なら if / else if / else、1つの値を多くの候補と比べるなら switch が読みやすくなります。
// switch:1つの値(day)を複数の候補と照合
switch (day) {
case "Sat":
case "Sun":
return "週末";
default:
return "平日";
}
| 観点 | if / else | switch |
|---|---|---|
| 得意なこと | 範囲・複数条件の組み合わせ | 1つの値の等値比較を多数 |
| 条件の自由度 | 高い(`a > 0 && b < 10` など) | 低い(基本は等値マッチ) |
| フォールスルー | なし | あり(break 忘れで次の case へ流れる) |
C系言語(C / Java / JavaScript など)の switch は、case に break を書かないと次の case の処理まで実行が流れ落ちます(フォールスルー)。これは意図的に使うこともありますが、多くは単なる書き忘れによるバグ。逆に Go や Rust は明示しない限り流れ落ちません。自分の使う言語の挙動を必ず確認してください。
反復:for / while / foreach
繰り返しの書き方は、おおむね3系統に分かれます。
| 種類 | 向く場面 | イメージ |
|---|---|---|
| for(カウンタ) | 回数が決まっている繰り返し | 「i を 0 から 9 まで」 |
| while | 終了条件が動的・回数が読めない | 「データが尽きるまで」 |
| foreach / for-of | コレクションの全要素を順に処理 | 「配列の各要素について」 |
# foreach:要素そのものを順番に取り出す(インデックス管理が不要)
for name in ["Alice", "Bob", "Carol"]:
print(name)
foreach 系はインデックスを自分で増減させないぶん、「1つずれ(off-by-one)」エラーや上限の書き間違いが起きにくく、コレクションを全件処理するなら第一候補です。
break と continue
ループの途中で流れを変える2つのキーワードです。混同しやすいので区別を押さえましょう。
| キーワード | 効果 | 使いどころ |
|---|---|---|
| break | ループ自体を即座に抜ける | 目的の要素が見つかった瞬間に探索終了 |
| continue | 今回の周回だけ飛ばし、次の周回へ | 条件に合わない要素をスキップ |
for (const n of numbers) {
if (n < 0) continue; // 負数は飛ばして次へ
if (n > 100) break; // 100超が来たら探索を打ち切り
sum += n;
}
早期returnでネストを浅く保つ
条件分岐を素直にネストすると、if の入れ子が深くなり「矢印コード(インデントが右に伸びて矢印状になる)」になりがちです。これは読みづらく、バグの温床。
// ✗ ネストが深い
function getPrice(user, item) {
if (user) {
if (item) {
if (item.inStock) {
return item.price;
}
}
}
return null;
}
条件を満たさないケースを先に return で弾く(ガード節) と、本筋の処理がフラットになります。
// ✓ ガード節で早期return
function getPrice(user, item) {
if (!user) return null;
if (!item) return null;
if (!item.inStock) return null;
return item.price; // 本筋はネストなし
}
入れ子が3段以上になったら、ガード節での早期return・関数の切り出し・ループからの早期break を検討する合図です。「正常系を左端に揃える」 と意識すると、コードの見通しが一気に良くなります。型ごとの分岐が多い場合はポリモーフィズムで分岐自体を消せることも。
つまずきポイント:無限ループ
while ループは終了条件がいつまでも偽にならないと、永遠に回り続けます(無限ループ)。CPU を食いつぶし、プログラムが固まる典型的なバグです。
let i = 0;
while (i < 10) {
console.log(i);
// i++ を書き忘れると i は 0 のまま → 永遠に終わらない
}
原因の多くは「カウンタの更新忘れ」か「終了条件に絶対到達しない」のどちらか。たとえば浮動小数点で while (x != 1.0) と書くと、誤差で 1.0 にピタリと一致せず止まらないことがあります。比較は < / <= を使う、ループ変数が毎回ゴールへ近づくか確認する、が予防策。なお while (true) { ... break; } のように意図的な無限ループ+break は、サーバーの待ち受けなどで正当に使われる定石でもあります。
まとめ
- 制御構文は 順次・分岐・反復 の3要素。これらの組み合わせがロジックのすべて。
- 条件は 真偽値 に評価される。truthy/falsy の曖昧さに注意し、迷ったら明示的に比較する。
- 早期return とガード節 でネストを浅く保つのが、読みやすさへの一番の近道。
- ループは 更新忘れ・到達不能な終了条件 で無限ループ化する。終了条件は必ず見直す。
プログラミング Article
制御構文(条件分岐とループ)を実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
制御構文
比較で見る軸
難易度: basic / カテゴリ: プログラミング / タグ数: 4
導入後に効く点
条件は最終的に真偽値(true/false)に評価される。break で抜け、continue で次の周回へ飛ぶ。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- basic
- カテゴリ
- プログラミング
- タグ数
- 4
判断チェックリスト
- 自社の用途が「制御構文 / 条件分岐」に近いか確認する。
- 強みである「制御構文は実行の流れを操る3要素=順次・分岐・反復の組み合わせがすべて。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。