C言語による制御構造と乱数処理の実践演習

本演習では、C言語における反復処理(whilefor)、分岐処理(ifswitch)、乱数生成、および基本的な入出力操作を統合的に活用する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が入力された時点で終了します。合計金額、最大値、最小値を計算して表示します。初期値としてmaxminには最初の有効値を代入するよう設計しています。

#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;
}

タグ: c-language random-number loop-control switch-statement scanf

6月21日 17:37 投稿