C言語 条件分岐(if文・switch文)の練習問題

if文・switch文で条件分岐する問題を、初級から上級まで12問そろえました。ブラウザでコードを書いて「採点する」を押すと、本物の gcc でいくつかの入力を試し、出力が正しいかを判定します。

この練習問題の使い方
  1. 問題文と実行例を読み、下の欄にコードを書く
  2. 「▶ 実行」で自分で入力を与えて動かしてみる
  3. 「✔ 採点する」で、用意したいくつかの入力に対して出力が正しいかを判定
  4. 行き詰まったら「ヒント」、解けたら「模範解答と解説」で確認
採点のルール
  • 出力は実行例と同じ形で表示する。「数を入力してください」のような入力を促すメッセージは表示しない
  • 行末の空白と、最後の空行の有無は区別しない
  • 書いたコードはこのブラウザに自動保存されます

※ 実行と採点では、コードを外部の無料コンパイルサービス Wandbox に送信して gcc で動かします。

全12問(初級 4・中級 5・上級 3)

if文・switch文の練習問題(12問)

I01 初級

問1. 正・負・ゼロの判定

整数 N(−10000 ≤ N ≤ 10000)を入力し、正なら「正の数」、負なら「負の数」、0 なら「ゼロ」と表示せよ。
実行例(下線が入力)
-3 負の数
コードを書く
「実行」で入力を与えて動かす/「採点する」で 5 個のテストを自動で試します
3通りに分けるので if 〜 else if 〜 else を使います。n > 0、n < 0 を順に調べ、どちらでもなければ 0 です。
#include <stdio.h>

int main(void) {
    int n;
    scanf("%d", &n);

    if (n > 0) {
        printf("正の数\n");
    } else if (n < 0) {
        printf("負の数\n");
    } else {
        printf("ゼロ\n");
    }
    return 0;
}
解説:if を3つ独立に並べても動きますが、else if でつなぐとどれか1つだけが実行されることがはっきりします。0 との比較を if (n = 0) と書くと代入になり、n が 0 に書き換わったうえで条件は常に偽になるので注意しましょう(比較は ==)。
I02 初級

問2. 偶数か奇数か

整数 N(−10000 ≤ N ≤ 10000)を入力し、偶数なら「Nは偶数です」、奇数なら「Nは奇数です」と表示せよ(N には入力した値が入る)。負の数も入力されることに注意。
実行例(下線が入力)
7 7は奇数です
コードを書く
「実行」で入力を与えて動かす/「採点する」で 5 個のテストを自動で試します
2 で割った余り n % 2 が 0 なら偶数です。奇数の判定を n % 2 == 1 と書くと、負の数でうまくいきません。
#include <stdio.h>

int main(void) {
    int n;
    scanf("%d", &n);

    if (n % 2 == 0) {
        printf("%dは偶数です\n", n);
    } else {
        printf("%dは奇数です\n", n);
    }
    return 0;
}
解説:C の % は割られる数が負だと余りも負になり、−3 % 2 は −1 です。そのため if (n % 2 == 1) で奇数を判定すると −3 が「偶数」と判定されてしまいます。「0 かどうか」で判定すれば符号に関係なく正しく動きます。
I03 初級

問3. 2つの数の大きい方

整数 a, b を空白区切りで入力し、大きい方の値を「大きい方: 値」と表示せよ。2つが等しいときは「同じ値です」と表示する。
実行例(下線が入力)
3 7 大きい方: 7
コードを書く
「実行」で入力を与えて動かす/「採点する」で 5 個のテストを自動で試します
まず a == b を調べて等しい場合を先に処理し、残りを a > b で分けると簡単です。
#include <stdio.h>

int main(void) {
    int a, b;
    scanf("%d %d", &a, &b);

    if (a == b) {
        printf("同じ値です\n");
    } else if (a > b) {
        printf("大きい方: %d\n", a);
    } else {
        printf("大きい方: %d\n", b);
    }
    return 0;
}
解説:if (a > b) … else … の2分岐だけだと、等しいときに else 側に入って「大きい方: 5」と表示されてしまいます。等しい場合(境界)をどちらに入れるかは、条件分岐で毎回意識するポイントです。
I04 初級

問4. 点数の範囲チェック

整数 x を入力し、0 以上 100 以下なら「有効な点数です」、それ以外なら「範囲外です」と表示せよ。
実行例(下線が入力)
101 範囲外です
コードを書く
「実行」で入力を与えて動かす/「採点する」で 5 個のテストを自動で試します
「0 以上かつ 100 以下」なので、論理積 && で2つの比較をつなぎます。0 <= n <= 100 とは書けません。
#include <stdio.h>

int main(void) {
    int n;
    scanf("%d", &n);

    if (n >= 0 && n <= 100) {
        printf("有効な点数です\n");
    } else {
        printf("範囲外です\n");
    }
    return 0;
}
解説:0 <= n <= 100 は (0 <= n) <= 100 と解釈されます。0 <= n の結果は 0 か 1 なので、それを 100 と比べると常に真になり、101 も −1 も「有効」になってしまいます(コンパイラによっては警告が出ます)。範囲は必ず && で書きましょう。
I05 中級

問5. 成績の評価

点数(0 以上 100 以下の整数)を入力し、90 点以上なら S、80 点以上なら A、70 点以上なら B、60 点以上なら C、60 点未満なら D として「評価: S」の形で表示せよ。
実行例(下線が入力)
85 評価: A
コードを書く
「実行」で入力を与えて動かす/「採点する」で 5 個のテストを自動で試します
点数の高い方から順に if (n >= 90) 〜 else if (n >= 80) 〜 と並べると、「80 以上 90 未満」のような2つの条件を書かずに済みます。
#include <stdio.h>

int main(void) {
    int n;
    scanf("%d", &n);

    char grade;
    if (n >= 90) {
        grade = 'S';
    } else if (n >= 80) {
        grade = 'A';
    } else if (n >= 70) {
        grade = 'B';
    } else if (n >= 60) {
        grade = 'C';
    } else {
        grade = 'D';
    }
    printf("評価: %c\n", grade);
    return 0;
}
解説:else if は上から順に調べて、最初に真になったところだけを実行します。else if (n >= 80) に来た時点で「90 未満」は確定しているので、n < 90 を書き足す必要はありません。逆に n >= 60 を先に書くと、100 点でも C になります。境界の 90・60 ちょうどのテストで > と >= の取り違えを確かめています。
I06 中級

問6. 3つの数の最大値と最小値

整数 a, b, c を空白区切りで入力し、最大値と最小値を表示せよ。
実行例(下線が入力)
3 9 2 最大: 9 最小: 2
コードを書く
「実行」で入力を与えて動かす/「採点する」で 5 個のテストを自動で試します
最大値を入れる変数 max にまず a を入れ、b が大きければ置き換え、c が大きければ置き換え…と1つずつ比べていくと、組み合わせを考えずに済みます。
#include <stdio.h>

int main(void) {
    int a, b, c;
    scanf("%d %d %d", &a, &b, &c);

    int max = a, min = a;
    if (b > max) max = b;
    if (c > max) max = c;
    if (b < min) min = b;
    if (c < min) min = c;

    printf("最大: %d\n", max);
    printf("最小: %d\n", min);
    return 0;
}
解説:ここでは else を付けず、独立した if を並べるのがポイントです(b と c の両方を必ず調べたいため)。if (a > b && a > c) のように組み合わせで書く方法では、7 7 1 のような同じ値があるときにどの条件にも当てはまらない、という間違いが起きやすくなります。最大値の初期値を 0 にすると、全部負のときに 0 が出てしまいます。
I07 中級

問7. うるう年の判定

西暦 Y(1 ≤ Y ≤ 9999)を入力し、うるう年なら「Y年はうるう年です」、そうでなければ「Y年は平年です」と表示せよ。うるう年は「4 で割り切れる年。ただし 100 で割り切れる年は除く。ただし 400 で割り切れる年はうるう年」とする。
実行例(下線が入力)
2024 2024年はうるう年です
コードを書く
「実行」で入力を与えて動かす/「採点する」で 5 個のテストを自動で試します
条件を論理演算子で1つの式にまとめると「(4 で割り切れて 100 で割り切れない) または 400 で割り切れる」です。&& と || を混ぜるときはカッコを付けましょう。
#include <stdio.h>
#include <stdbool.h>

int main(void) {
    int y;
    scanf("%d", &y);

    bool leap = (y % 4 == 0 && y % 100 != 0) || y % 400 == 0;

    if (leap) {
        printf("%d年はうるう年です\n", y);
    } else {
        printf("%d年は平年です\n", y);
    }
    return 0;
}
解説:「4 で割り切れればうるう年」だけだと 1900 年や 2100 年を間違えます。条件の結果を bool(<stdbool.h>)の変数に入れておくと、if (leap) と読みやすく書けます。&& は || より優先順位が高いのでカッコがなくても同じ意味になりますが、読み手のためにカッコを付けるのがおすすめです。
I08 中級

問8. 月の日数(switch文)

月 M を整数で入力し、平年(2月は28日)のその月の日数を「M月は30日です」の形で表示せよ。M が 1〜12 以外なら「不正な月です」と表示する。switch文を使うこと。
実行例(下線が入力)
4 4月は30日です
コードを書く
「実行」で入力を与えて動かす/「採点する」で 5 個のテストを自動で試します
日数が同じ月は case 4: case 6: case 9: case 11: のように case を縦に並べてまとめられます。1〜12 以外は default で受けます。
#include <stdio.h>

int main(void) {
    int m;
    scanf("%d", &m);

    int days;
    switch (m) {
    case 1: case 3: case 5: case 7: case 8: case 10: case 12:
        days = 31;
        break;
    case 4: case 6: case 9: case 11:
        days = 30;
        break;
    case 2:
        days = 28;
        break;
    default:
        printf("不正な月です\n");
        return 0;
    }
    printf("%d月は%d日です\n", m, days);
    return 0;
}
解説:switch は一致した case からbreak までの文を順に実行します。この性質を使うと、文のない case を並べて「どれかに一致したら同じ処理」が書けます。逆に break を書き忘れると、4月のあと次の case の処理まで続けて実行されてしまうので注意しましょう。
I09 中級

問9. じゃんけんの勝敗

A と B の手を整数で空白区切りに入力する(0: グー、1: チョキ、2: パー)。1行目に「A: グー B: チョキ」のように両者の手を表示し、2行目に「Aの勝ち」「Bの勝ち」「あいこ」のいずれかを表示せよ。
実行例(下線が入力)
0 1 A: グー B: チョキ Aの勝ち
コードを書く
「実行」で入力を与えて動かす/「採点する」で 5 個のテストを自動で試します
手の名前の表示は switch文で書けます。勝敗は9通りを全部書いてもよいですが、(a - b + 3) % 3 を計算すると、0 ならあいこ、2 なら A の勝ち、1 なら B の勝ちになります。
#include <stdio.h>

void print_hand(int h) {
    switch (h) {
    case 0: printf("グー"); break;
    case 1: printf("チョキ"); break;
    case 2: printf("パー"); break;
    }
}

int main(void) {
    int a, b;
    scanf("%d %d", &a, &b);

    printf("A: ");
    print_hand(a);
    printf(" B: ");
    print_hand(b);
    printf("\n");

    int r = (a - b + 3) % 3;
    if (r == 0) {
        printf("あいこ\n");
    } else if (r == 2) {
        printf("Aの勝ち\n");
    } else {
        printf("Bの勝ち\n");
    }
    return 0;
}
解説:グー(0)→チョキ(1)→パー(2)→グー と、番号が1つ大きい手に勝つ並びになっているので、差 a − b を 3 で割った余りで勝敗が決まります。+ 3 を忘れると a − b が負のとき余りも負になり(例: −1 % 3 は −1)、判定がずれます。関数をまだ習っていなければ、switch を main の中に2回書いても構いません。
I10 上級

問10. 簡単な電卓

「整数 演算子 整数」の形の式(例: 7 / 2)を入力し、計算結果を「7 / 2 = 3」の形で表示せよ。演算子は + - * / % の5種類で、/ と % は C の整数の割り算・余りとする。/ または % で右辺が 0 のときは「エラー: 0で割ることはできません」、それ以外の演算子なら「エラー: 不明な演算子です」と表示する(整数は −10000〜10000)。
実行例(下線が入力)
7 / 2 7 / 2 = 3
コードを書く
「実行」で入力を与えて動かす/「採点する」で 5 個のテストを自動で試します
演算子の文字で switch (op) と分岐し、case '+': のように文字定数で比べます。/ と % の case の中で、先に b == 0 を調べます。
#include <stdio.h>

int main(void) {
    int a, b;
    char op;
    scanf("%d %c %d", &a, &op, &b);

    int result;
    switch (op) {
    case '+':
        result = a + b;
        break;
    case '-':
        result = a - b;
        break;
    case '*':
        result = a * b;
        break;
    case '/':
    case '%':
        if (b == 0) {
            printf("エラー: 0で割ることはできません\n");
            return 0;
        }
        result = (op == '/') ? a / b : a % b;
        break;
    default:
        printf("エラー: 不明な演算子です\n");
        return 0;
    }
    printf("%d %c %d = %d\n", a, op, b, result);
    return 0;
}
解説:0 で割る計算は未定義動作で、プログラムが異常終了することもあるため、割る前にチェックします。scanf の %c の前に空白を入れた " %c"(ここでは "%d %c %d")は、手前の空白を読み飛ばしてから1文字を読む指定です。空白がないと、数字の後ろの空白が op に入ってしまいます。
I11 上級

問11. 三角形の判定

3辺の長さ a, b, c(1〜1000 の整数、順不同)を入力し、三角形が作れなければ「三角形ではありません」と表示せよ。作れる場合は、正三角形なら「正三角形」、二等辺三角形なら「二等辺三角形」、直角三角形なら「直角三角形」、どれでもなければ「普通の三角形」と表示する。正三角形は「正三角形」とだけ表示する。三角形が作れる条件は「どの2辺の和も残りの1辺より長い」こと。
実行例(下線が入力)
5 3 4 直角三角形
コードを書く
「実行」で入力を与えて動かす/「採点する」で 5 個のテストを自動で試します
判定の順番が大切です。①三角形が作れるか → ②3辺とも等しいか → ③2辺が等しいか → ④直角か、の順に else if でつなぎます。直角は辺の順番が決まっていないので、3通りの a*a + b*b == c*c を || でつなぎます。
#include <stdio.h>

int main(void) {
    int a, b, c;
    scanf("%d %d %d", &a, &b, &c);

    if (a + b <= c || b + c <= a || c + a <= b) {
        printf("三角形ではありません\n");
    } else if (a == b && b == c) {
        printf("正三角形\n");
    } else if (a == b || b == c || c == a) {
        printf("二等辺三角形\n");
    } else if (a * a + b * b == c * c || b * b + c * c == a * a || c * c + a * a == b * b) {
        printf("直角三角形\n");
    } else {
        printf("普通の三角形\n");
    }
    return 0;
}
解説:2 5 2 は2辺が等しいですが、2 + 2 < 5 なので三角形になりません。成立判定を最初にしないと「二等辺三角形」と誤って表示されます。同様に、正三角形は二等辺三角形の条件も満たすので、より厳しい条件(正三角形)を先に判定します。a == b == c は (a == b) == c の意味になるので、&& で書きます(辺が整数なので、直角二等辺三角形はこの問題では現れません)。
I12 上級

問12. 2つの日付の前後

2つの日付を「年 月 日」の形で1行ずつ入力し(どちらも実在する日付)、1つ目が前なら「1つ目の日付が前です」、2つ目が前なら「2つ目の日付が前です」、同じなら「同じ日付です」と表示せよ。
実行例(下線が入力)
2024 3 15 2024 3 20 1つ目の日付が前です
コードを書く
「実行」で入力を与えて動かす/「採点する」で 5 個のテストを自動で試します
年 → 月 → 日 の順に比べます。「年が小さい、または年が同じで月が小さい、または年も月も同じで日が小さい」を || と && で1つの条件にできます。
#include <stdio.h>

int main(void) {
    int y1, m1, d1, y2, m2, d2;
    scanf("%d %d %d", &y1, &m1, &d1);
    scanf("%d %d %d", &y2, &m2, &d2);

    if (y1 == y2 && m1 == m2 && d1 == d2) {
        printf("同じ日付です\n");
    } else if (y1 < y2 || (y1 == y2 && m1 < m2) || (y1 == y2 && m1 == m2 && d1 < d2)) {
        printf("1つ目の日付が前です\n");
    } else {
        printf("2つ目の日付が前です\n");
    }
    return 0;
}
解説:y1 <= y2 && m1 <= m2 && d1 <= d2 のように各項目をばらばらに比べると、2023/12/31 と 2024/1/1 で月・日が大きいため誤判定になります。上の単位が等しいときだけ下の単位を比べるのが辞書式の比較です。別解として y * 10000 + m * 100 + d の1つの整数にして比べる方法もあります。

復習する講座

← 練習問題の一覧へ