if文・switch文で条件分岐する問題を、初級から上級まで12問そろえました。ブラウザでコードを書いて「採点する」を押すと、本物の gcc でいくつかの入力を試し、出力が正しいかを判定します。
※ 実行と採点では、コードを外部の無料コンパイルサービス Wandbox に送信して gcc で動かします。
正の数」、負なら「負の数」、0 なら「ゼロ」と表示せよ。「実行」で入力を与えて動かす/「採点する」で 5 個のテストを自動で試します
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 に書き換わったうえで条件は常に偽になるので注意しましょう(比較は ==)。Nは偶数です」、奇数なら「Nは奇数です」と表示せよ(N には入力した値が入る)。負の数も入力されることに注意。「実行」で入力を与えて動かす/「採点する」で 5 個のテストを自動で試します
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; }
% は割られる数が負だと余りも負になり、−3 % 2 は −1 です。そのため if (n % 2 == 1) で奇数を判定すると −3 が「偶数」と判定されてしまいます。「0 かどうか」で判定すれば符号に関係なく正しく動きます。大きい方: 値」と表示せよ。2つが等しいときは「同じ値です」と表示する。「実行」で入力を与えて動かす/「採点する」で 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」と表示されてしまいます。等しい場合(境界)をどちらに入れるかは、条件分岐で毎回意識するポイントです。有効な点数です」、それ以外なら「範囲外です」と表示せよ。「実行」で入力を与えて動かす/「採点する」で 5 個のテストを自動で試します
&& で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 も「有効」になってしまいます(コンパイラによっては警告が出ます)。範囲は必ず && で書きましょう。評価: S」の形で表示せよ。「実行」で入力を与えて動かす/「採点する」で 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 (n >= 80) に来た時点で「90 未満」は確定しているので、n < 90 を書き足す必要はありません。逆に n >= 60 を先に書くと、100 点でも C になります。境界の 90・60 ちょうどのテストで > と >= の取り違えを確かめています。「実行」で入力を与えて動かす/「採点する」で 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 が出てしまいます。Y年はうるう年です」、そうでなければ「Y年は平年です」と表示せよ。うるう年は「4 で割り切れる年。ただし 100 で割り切れる年は除く。ただし 400 で割り切れる年はうるう年」とする。「実行」で入力を与えて動かす/「採点する」で 5 個のテストを自動で試します
&& と || を混ぜるときはカッコを付けましょう。#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; }
bool(<stdbool.h>)の変数に入れておくと、if (leap) と読みやすく書けます。&& は || より優先順位が高いのでカッコがなくても同じ意味になりますが、読み手のためにカッコを付けるのがおすすめです。M月は30日です」の形で表示せよ。M が 1〜12 以外なら「不正な月です」と表示する。switch文を使うこと。「実行」で入力を与えて動かす/「採点する」で 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; }
A: グー B: チョキ」のように両者の手を表示し、2行目に「Aの勝ち」「Bの勝ち」「あいこ」のいずれかを表示せよ。「実行」で入力を与えて動かす/「採点する」で 5 個のテストを自動で試します
(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; }
+ 3 を忘れると a − b が負のとき余りも負になり(例: −1 % 3 は −1)、判定がずれます。関数をまだ習っていなければ、switch を main の中に2回書いても構いません。7 / 2)を入力し、計算結果を「7 / 2 = 3」の形で表示せよ。演算子は + - * / % の5種類で、/ と % は C の整数の割り算・余りとする。/ または % で右辺が 0 のときは「エラー: 0で割ることはできません」、それ以外の演算子なら「エラー: 不明な演算子です」と表示する(整数は −10000〜10000)。「実行」で入力を与えて動かす/「採点する」で 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; }
%c の前に空白を入れた " %c"(ここでは "%d %c %d")は、手前の空白を読み飛ばしてから1文字を読む指定です。空白がないと、数字の後ろの空白が op に入ってしまいます。三角形ではありません」と表示せよ。作れる場合は、正三角形なら「正三角形」、二等辺三角形なら「二等辺三角形」、直角三角形なら「直角三角形」、どれでもなければ「普通の三角形」と表示する。正三角形は「正三角形」とだけ表示する。三角形が作れる条件は「どの2辺の和も残りの1辺より長い」こと。「実行」で入力を与えて動かす/「採点する」で 5 個のテストを自動で試します
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 の意味になるので、&& で書きます(辺が整数なので、直角二等辺三角形はこの問題では現れません)。1つ目の日付が前です」、2つ目が前なら「2つ目の日付が前です」、同じなら「同じ日付です」と表示せよ。「実行」で入力を与えて動かす/「採点する」で 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つの整数にして比べる方法もあります。