
C言語基礎|配列を使った分布処理
配列で値を読み込めるようになって、最大・最小も取れるようになったら、次はもう一段レベルアップです。
それが 分布処理。つまり「どの範囲にデータが多い?」を集計して、見える化するやつです。
たとえば…
- テスト点の 0~9 点が何人、10~19 点が何人…
- 気温の 0~4℃ が何日、5~9℃ が何日…
- 年齢の 20 代が何人、30 代が何人…
こういう “集計用の配列(カウンタ配列)” を作ると、配列の面白さが一気に広がります。

まず全体像:2種類の配列が登場する
分布処理では、たいてい次の2つを同時に使います。
| 配列 | 役割 | 例 |
|---|---|---|
| 入力データの配列 | 元データを保存する | data[i] に入力値 |
| 分布(カウント)の配列 | 範囲ごとの件数を数える | hist[k] に件数 |
図でイメージするとこんな感じです。

「入力」と「集計」を分けると、コードも考え方もスッキリします。
配列の要素数を多めに確保して、一部だけ使う(num方式)
現場でもよくやる方法です。
- 配列は最大サイズ MAX で確保しておく
- 実際に使うのは先頭 num 個だけ
| 変数/マクロ | 意味 |
|---|---|
| MAX | 配列に入れられる最大件数(上限) |
| num | 実際に入力した件数(実行中に決まる) |
この方式のメリットは、「人数が変わっても配列のサイズ自体はいじらなくていい」こと。
入力制限(1~MAX)を入れておくと、配列範囲外アクセスも防げます。
サンプルプログラム
1日の気温(0~40℃) を複数日分入力して、5℃刻みの分布 を表示するプログラムを例に解説をします。
- 入力件数:1~MAX_DAYS
- 気温:0~40
- 分布:0~4, 5~9, …, 35~39, 40(最後だけ単独)
プロジェクト名:chap5-7-1 ソースファイル名:chap5-7-1.c
Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。
// 気温を読み込んで分布(ヒストグラム)を表示
#include <stdio.h>
#define MAX_DAYS 60 // 入力日数の上限
#define MAX_TEMP 40 // 気温の最大値(0~40)
#define STEP 5 // 階級幅(5℃刻み)
#define BINS (MAX_TEMP / STEP + 1) // 0..40 を 5刻み → 9個(最後に40用)
int main(void)
{
int days; // 実際に入力する日数
int temp[MAX_DAYS]; // 気温データ
int hist[BINS] = {0}; // 分布(件数)
printf("入力する日数を入れてください:");
do {
scanf("%d", &days);
if (days < 1 || days > MAX_DAYS)
printf("1~%dの範囲で入力してください:", MAX_DAYS);
} while (days < 1 || days > MAX_DAYS);
printf("%d日分の気温(0~40)を入力してください。\n", days);
for (int i = 0; i < days; i++) {
printf("%d日目:", i + 1);
do {
scanf("%d", &temp[i]);
if (temp[i] < 0 || temp[i] > MAX_TEMP)
printf("0~%dで入力してください:", MAX_TEMP);
} while (temp[i] < 0 || temp[i] > MAX_TEMP);
hist[temp[i] / STEP]++; // 分布カウント
}
puts("\n--- 気温の分布 ---");
printf("%d:", MAX_TEMP);
for (int j = 0; j < hist[BINS - 1]; j++)
putchar('*');
putchar('\n');
for (int k = BINS - 2; k >= 0; k--) {
printf("%2d~%2d:", k * STEP, k * STEP + (STEP - 1));
for (int j = 0; j < hist[k]; j++)
putchar('*');
putchar('\n');
}
return 0;
}分布カウントの肝:hist[temp[i] / STEP]++
ここがこの節のいちばん気持ちいいポイントです。
整数 / 整数 の割り算は小数部が切り捨てられるので、範囲分けにピッタリ。
例(STEP が 5 のとき)
| temp[i] | temp[i] / 5 | 増える要素 | どの範囲? |
|---|---|---|---|
| 0 | 0 | hist[0] | 0~4 |
| 4 | 0 | hist[0] | 0~4 |
| 5 | 1 | hist[1] | 5~9 |
| 9 | 1 | hist[1] | 5~9 |
| 10 | 2 | hist[2] | 10~14 |
| 39 | 7 | hist[7] | 35~39 |
| 40 | 8 | hist[8] | 40(最後) |
つまり「入力値を割るだけで、どの箱に入るかが決まる」わけです。
表示部分の考え方:分布配列を星で描く
分布配列 hist の中身は「件数」です。
件数回だけ * を出せば、横向き棒グラフになります。
| やっていること | コードの形 |
|---|---|
| hist[k] 回だけ繰り返す | for (j = 0; j < hist[k]; j++) |
| 1文字出力 | putchar('*'); |
この節で使う入力チェック(do-while)の意味
入力は「範囲外が来たら聞き直す」のが実用的です。
そこで do-while が活躍します。
do-while の書式
do {
繰り返す処理
} while (条件);何をする命令?
必ず1回は処理を実行し、そのあと条件が真なら繰り返します。
「入力→チェック→ダメなら再入力」という流れにピッタリです。
登場する命令・演算子の書式と役割まとめ
| 名前 | 書式 | 何をする? |
|---|---|---|
| #define 指令 | #define 名前 値 | 翻訳時に定数へ置換し、上限や刻み幅を一元管理する。 |
| for 文 | for (初期化; 条件; 更新) { } | 配列を走査したり、星を出したりする繰り返し。 |
| do-while 文 | do { } while (条件); | 入力値が正しいまで再入力させる。 |
| if 文 | if (条件) 文; | 範囲外のときメッセージを出す。 |
| scanf | scanf(書式, 格納先アドレス); | キーボード入力を配列要素へ格納 |
| puts | puts(文字列); | 1行表示(改行付き) |
| putchar | putchar(文字); | 1文字表示(グラフ用の*など) |
| /(整数除算) | a / b | 小数部切り捨て、階級(bin)計算に使う。 |
| ++ | hist[k]++ | 件数を1増やす。 |
分布処理の流れ
(1) days を入力(1~MAX)
|
v
(2) temp[i] を入力(0~MAX_TEMP)
|
v
(3) bin = temp[i] / STEP を計算
|
v
(4) hist[bin] を 1 増やす
|
v
(5) hist を使って棒グラフ表示
この流れを覚えると、題材が点数でも気温でも年齢でも、同じパターンで作れます。
演習問題
演習 5-6
配列に格納するデータ数と要素の値を読み込み、全要素をコンマとスペース区切りで { と } で囲んで表示せよ。
配列の要素数の上限はオブジェクト形式マクロで定義すること。
解答例
プロジェクト名:chap5-7-2 ソースファイル名:chap5-7-2.c
Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。
#include <stdio.h>
#define MAX 100
int main(void)
{
int n, a[MAX];
printf("データ数:");
do {
scanf("%d", &n);
if (n < 1 || n > MAX)
printf("1~%dで入力してください:", MAX);
} while (n < 1 || n > MAX);
for (int i = 0; i < n; i++) {
printf("%d番:", i + 1);
scanf("%d", &a[i]);
}
putchar('{');
for (int i = 0; i < n; i++) {
if (i > 0) printf(", ");
printf("%d", a[i]);
}
puts("}");
return 0;
}演習5-7
分布グラフの表示を逆順(低い範囲から高い範囲)に表示するプログラムを作成せよ。
解答例(表示部分だけ)
puts("\n--- Distribution (low to high) ---");
for (int k = 0; k < BINS - 1; k++) {
printf("%2d~%2d:", k * STEP, k * STEP + (STEP - 1));
for (int j = 0; j < hist[k]; j++)
putchar('*');
putchar('\n');
}
printf("%d:", MAX_TEMP);
for (int j = 0; j < hist[BINS - 1]; j++)
putchar('*');
putchar('\n');演習5-8
分布グラフを縦方向に表示するプログラムを作成せよ。
解答例(考え方+簡易コード)
まず最大件数(棒の高さ)を求めて、その高さから下へ描きます。
int maxc = hist[0];
for (int k = 1; k < BINS; k++)
if (hist[k] > maxc) maxc = hist[k];
for (int row = maxc; row >= 1; row--) {
for (int k = 0; k < BINS; k++) {
if (hist[k] >= row) printf("* ");
else printf(" ");
}
putchar('\n');
}
for (int k = 0; k < BINS; k++) printf("--");
putchar('\n');
for (int k = 0; k < BINS - 1; k++) printf("%d ", k * STEP);
printf("%d\n", MAX_TEMP);