C言語基礎練習:制御フローと乱数処理の応用

本稿では、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ループ内で完結し、最後に答えを教える。

タグ: C言語 制御フロー 乱数 入力処理 三角形判定

8月28日 16:20 投稿