本演習では、C言語における反復処理(while・for)、分岐処理(if・switch)、乱数生成、および基本的な入出力操作を統合的に活用する6つの課題を実施します。
課題1:動的学籍番号生成器
固定プレフィックス「20490042」に、1~100の範囲でランダムに選ばれた4桁整数を連結し、5件分出力します。乱数シードは現在時刻に基づき初期化されます。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
const int COUNT = 5;
srand((unsigned int)time(NULL));
for (int idx = 0; idx < COUNT; ++idx) {
int random_value = rand() % 100 + 1;
printf("20490042%04d\n", random_value);
}
return 0;
}課題2:簡易飲料販売機シミュレータ
メニュー選択→数量入力→支払い金額入力→精算のフローを実装。各購入後には合計金額をリセットし、次の取引に備えます。不正な入力(無効な商品番号・負の数量)に対してはエラーメッセージを表示して再入力を促します。
#include <stdio.h>
int main() {
float cumulative_cost = 0.0f;
int selection;
while (1) {
printf("\n=== 飲料自動販売機 ===\n");
printf("1: コーラ (¥3)\n");
printf("2: サイダー (¥3)\n");
printf("3: オレンジジュース (¥5)\n");
printf("4: ミネラルウォーター (¥2)\n");
printf("0: 終了\n");
printf("選択してください: ");
scanf("%d", &selection);
if (selection == 0) break;
if (selection < 1 || selection > 4) {
printf("※ 不正な選択です。再入力してください。\n");
continue;
}
int count;
printf("個数を入力: ");
scanf("%d", &count);
if (count < 0) {
printf("※ 個数は0以上で指定してください。\n");
continue;
}
switch (selection) {
case 1:
case 2:
cumulative_cost += 3.0f * count;
break;
case 3:
cumulative_cost += 5.0f * count;
break;
case 4:
cumulative_cost += 2.0f * count;
break;
}
float payment;
printf("支払金額を入力: ");
scanf("%f", &payment);
printf("合計: ¥%.2f\n", cumulative_cost);
printf("お釣り: ¥%.2f\n", payment - cumulative_cost);
cumulative_cost = 0.0f; // 次回取引のため初期化
}
printf("ご利用ありがとうございました。\n");
return 0;
}課題3:交通信号コマンドインタフェース
単一文字入力('r', 'g', 'y')に基づき、対応する動作メッセージを即時出力します。入力バッファのクリアにgetchar()を挿入し、改行文字の干渉を防止します。
#include <stdio.h>
int main() {
char command;
printf("信号コマンド: r=停止, g=進行, y=待機\n");
while (1) {
scanf(" %c", &command); // 先頭空白で改行をスキップ
switch (command) {
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 just be wrong...\n");
}
}
return 0;
}課題4:消費明細集計ツール
浮動小数点数の連続入力を受け付け、-1が入力された時点で終了します。合計金額、最大値、最小値を計算して表示します。初期値としてmaxとminには最初の有効値を代入するよう設計しています。
#include <stdio.h>
int main() {
float amount, total = 0.0f, max_val, min_val;
int first_input = 1;
printf("消費金額を入力(終了: -1):\n");
while (1) {
scanf("%f", &amount);
if (amount == -1.0f) break;
total += amount;
if (first_input) {
max_val = min_val = amount;
first_input = 0;
} else {
if (amount > max_val) max_val = amount;
if (amount < min_val) min_val = amount;
}
}
printf("今日累计消费总额:%.1f\n", total);
printf("今日最高一笔开销:%.1f\n", max_val);
printf("今日最低一笔开销:%.1f\n", min_val);
return 0;
}課題5:ラッキーデイ予測ゲーム
1~30の範囲で乱数を生成し、ユーザーに3回の推測チャンスを与えます。推測値と正解を比較してヒントを提供し、全失敗時には正解を明示します。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
srand((unsigned int)time(NULL));
const int MAX_ATTEMPTS = 3;
const int TARGET_MIN = 1, TARGET_MAX = 30;
int target_day = rand() % (TARGET_MAX - TARGET_MIN + 1) + TARGET_MIN;
int guess;
printf("2025年4月のラッキーデイを当ててください(1〜30)\n");
printf("チャンスは%d回です。\n", MAX_ATTEMPTS);
for (int attempt = 0; attempt < MAX_ATTEMPTS; ++attempt) {
printf("推測 %d: ", attempt + 1);
scanf("%d", &guess);
if (guess == target_day) {
printf("正解!おめでとうございます。\n");
return 0;
} else if (guess < target_day) {
printf("早すぎます。もう少し先の日付です。\n");
} else {
printf("遅すぎます。もっと前の日付です。\n");
}
}
printf("残念でした。正解は %d 日でした。\n", target_day);
return 0;
}課題6:階層型ピラミッド描画
ユーザー指定の段数に基づき、三段構成(数字「0」、記号「<H>」、文字列「I I」)の逆三角形パターンを生成します。各行のインデント幅は段数に比例し、視覚的な中心揃えを実現します。
#include <stdio.h>
int main() {
int height;
printf("ピラミッドの段数を入力: ");
scanf("%d", &height);
for (int level = height; level > 0; --level) {
// 左右の空白(インデント)
for (int pad = 0; pad < height - level; ++pad) {
printf(" ");
}
// 「0」の行
for (int pos = 0; pos < 2 * level - 1; ++pos) {
printf(" 0 ");
}
printf("\n");
// 「<H>」の行
for (int pad = 0; pad < height - level; ++pad) {
printf(" ");
}
for (int pos = 0; pos < 2 * level - 1; ++pos) {
printf("<H>");
}
printf("\n");
// 「I I」の行
for (int pad = 0; pad < height - level; ++pad) {
printf(" ");
}
for (int pos = 0; pos < 2 * level - 1; ++pos) {
printf("I I");
}
printf("\n");
}
return 0;
}