本稿では、C言語の基本的な制御文(while, if-else, for)と乱数生成を組み合わせた6つの練習問題を紹介する。各コードは動作を簡潔に保ちつつ、変数名やロジックを一部変更してある。
1. ランダム学籍番号生成
現在時刻をシードに、2種類の学科からランダムに5人を選び、学籍番号(20256343に続く4桁)を出力する。学科の振り分けは乱数(0/1)で決定し、各学科の番号範囲は異なる。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define TOTAL 5
#define RANGE_A 80
#define RANGE_B 35
int main() {
int count = 0;
int dept, seq;
srand(time(NULL));
while (count < TOTAL) {
dept = rand() % 2;
if (dept == 0) {
seq = rand() % RANGE_A + 1;
printf("20256343%04d\n", seq);
} else {
seq = rand() % RANGE_B + 1;
printf("20256343%04d\n", seq);
}
count++;
}
return 0;
}
注意点:乱数シードを毎回変える必要はない。ループ内で学科を切り替えることで、均等に近い分布が得られる。
2. 簡易自動販売機
4種類の飲料を選び、数量を入力して合計金額を計算、支払い後の釣銭を表示する。メニューはループで繰り返し表示し、0を入力すると終了。不正な入力はスキップする。
#include <stdio.h>
int main() {
int item, qty;
float total = 0.0, pay, change;
while (1) {
printf("\n=== 自動販売機 ===\n");
printf("1. コーラ (3円)\n2. スプライト (3円)\n3. オレンジジュース (5円)\n4. ミネラルウォーター (2円)\n0. 終了\n");
printf("番号を入力: ");
scanf("%d", &item);
if (item == 0) break;
if (item < 1 || item > 4) {
printf("無効な番号です。\n");
continue;
}
printf("数量を入力: ");
scanf("%d", &qty);
if (qty < 0) {
printf("数量は0以上で入力してください。\n");
continue;
}
switch (item) {
case 1:
case 2: total += 3.0 * qty; break;
case 3: total += 5.0 * qty; break;
case 4: total += 2.0 * qty; break;
}
printf("合計金額: %.2f 円\n", total);
printf("投入金額を入力: ");
scanf("%f", &pay);
change = pay - total;
printf("お釣り: %.2f 円\n", change);
total = 0.0; // 次の購入に備えてリセット
}
printf("ご利用ありがとうございました。\n");
return 0;
}
注意点:合計金額を毎回リセットしないと前回の金額が残る。また、switch文を使うとコードが読みやすくなる。
3. 信号機シミュレーション
キーボードから'r','g','y'を入力し、対応するメッセージを表示。それ以外の文字はエラー扱い。EOFで終了。入力後に改行を消費する。
#include <stdio.h>
int main() {
char signal;
while ((signal = getchar()) != EOF) {
switch (signal) {
case 'r': printf("stop!\n"); break;
case 'g': printf("go go go\n"); break;
case 'y': printf("wait a minute\n"); break;
default: printf("something must be wrong...\n"); break;
}
getchar(); // 改行を読み飛ばす
}
return 0;
}
注意点:getchar()は改行文字も含むため、ループ内で1文字余分に読み取る必要がある。代わりにscanf("%c")を使う方法もある。
4. 1日の消費記録
金額を連続入力し、合計・最大・最小を計算する。0より大きく20000以下の金額のみ集計対象。入力終了は-1。
#include <stdio.h>
int main() {
double amount = 0.0;
double sum = 0.0;
double max = 0.0;
double min = 99999.0; // 大きな初期値
while (1) {
printf("金額を入力 (-1で終了): ");
scanf("%lf", &amount);
if (amount == -1) break;
if (amount <= 0 || amount > 20000) continue;
sum += amount;
if (amount > max) max = amount;
if (amount < min) min = amount;
}
printf("累計: %.1f\n", sum);
printf("最高額: %.1f\n", max);
printf("最低額: %.1f\n", min);
return 0;
}
注意点:minの初期値を十分大きな値にしないと、最初の比較で正しく更新されない。また、continueで不正な入力をスキップする。
5. 三角形の種類判定
3辺の長さを入力し、三角形の成立条件をチェックした後、正三角形・二等辺三角形・直角三角形・普通の三角形を判定する。EOFまで繰り返し。
#include <stdio.h>
int main() {
int a, b, c;
while (scanf("%d %d %d", &a, &b, &c) != EOF) {
// 三角形成立条件
if (a + b <= c || a + c <= b || b + c <= a) {
printf("三角形を形成できません\n");
continue;
}
if (a == b && b == c) {
printf("正三角形\n");
} else if (a == b || a == c || b == c) {
printf("二等辺三角形\n");
} else if (a*a + b*b == c*c || a*a + c*c == b*b || b*b + c*c == a*a) {
printf("直角三角形\n");
} else {
printf("普通の三角形\n");
}
}
return 0;
}
注意点:EOF入力はWindowsではCtrl+Z、Unix系ではCtrl+D。直角三角形の判定にはピタゴラスの定理を用いる。
6. ラッキーデイ当てゲーム
2025年11月のラッキーデイ(1~30のランダムな日)を3回のチャンスで当てる。ヒントとして「早い」「遅い」を表示。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
srand(time(NULL));
int lucky = rand() % 30 + 1;
int guess;
int chances = 3;
printf("2025年11月のあなたのラッキーデイを当ててください!\n");
printf("(1~30の整数、3回までチャンスあり)\n");
for (int i = 0; i < chances; i++) {
printf("%d回目: ", i + 1);
scanf("%d", &guess);
if (guess == lucky) {
printf("正解!ラッキーデイは%d日です!\n", lucky);
break;
} else if (guess > lucky) {
printf("遅すぎます。もっと前の日です。\n");
} else {
printf("早すぎます。もっと後の日です。\n");
}
if (i == chances - 1) {
printf("残念!正解は%d日でした。\n", lucky);
}
}
return 0;
}
注意点:乱数は実行ごとに変わる。ヒントの表示はforループ内で完結し、最後に答えを教える。