
C言語基礎|配列要素の最大値と最小値
配列に値を読み込めるようになると、次にやりたくなるのが「集計」系の処理です。
合計や平均も楽しいんですが、実務っぽさが一気に出るのがこれ:
- 最大値(max) … いちばん大きい値
- 最小値(min) … いちばん小さい値
たとえば、気温データの最高/最低、売上の最大/最小、センサー値のピーク…などなど。
この節では、配列を走査しながら max と min を同時に更新して求めるやり方を、やさしく整理していきますね。

最大値・最小値を求める基本アイデア
最大値を求める手順はすごくシンプルです。
- 「とりあえず最大値」を仮に決める(最初の要素を使うのが定番)
- 残りの要素を順番に見て、もっと大きいのがあったら更新する。
最小値も同じで、比較が逆になるだけです。
| 目的 | 比較 | 更新 |
|---|---|---|
| 最大値 max | 値 > max | max = 値 |
| 最小値 min | 値 < min | min = 値 |
サンプルプログラム(別例に差し替え版)
ここでは「1週間の歩数」を入力して、最大と最小を表示してみます。
プロジェクト名:chap5-6-1 ソースファイル名:chap5-6-1.c
Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。
// 1週間の歩数を読み込んで最大値と最小値を表示
#include <stdio.h>
#define DAYS 7 // データ数(1週間)
int main(void)
{
int steps[DAYS];
int max, min;
printf("%d日分の歩数を入力してください。\n", DAYS);
for (int i = 0; i < DAYS; i++) {
printf("%d日目:", i + 1);
scanf("%d", &steps[i]);
}
min = max = steps[0]; // 多重代入(最初の値で両方初期化)
for (int i = 1; i < DAYS; i++) {
if (steps[i] > max) max = steps[i];
if (steps[i] < min) min = steps[i];
}
printf("最も多い歩数:%d\n", max);
printf("最も少ない歩数:%d\n", min);
return 0;
}どうして最初に min = max = steps[0]; なの?
配列の最大・最小を求めるときにありがちなミスが、「初期値を雑に 0 にしてしまう」ことです。
たとえば全てマイナスのデータだったら、最大値が 0 のままになって壊れますよね。
そこで安全なのが 最初の要素を基準にするやり方です。
| 初期化方法 | 問題が起きやすい例 |
|---|---|
| max = 0; | 全部マイナスなら max が更新されない。 |
| min = 0; | 全部プラスなら min が更新されない可能性 |
| min = max = steps[0]; | データの範囲に依存せず自然に正しく動く。 |
多重代入(min = max = steps[0];)の意味を図で理解
代入は 右から左へ行われます。
だから次のように解釈されます。
min = (max = steps[0]);
処理の流れ(steps[0] が 8000 だった例)
- max = steps[0]; で max が 8000 になる
- この代入式全体の評価結果は「代入後の max の値(8000)」
- min = 8000 が実行される
図イメージ:

重要:代入式を評価すると「左側の型と値」になる
ここ、地味に強いルールです。
例:int 型変数 n に 2.95 を代入すると…
| 代入式 | 左側の型 | 代入後の値 | 代入式の評価結果 |
|---|---|---|---|
| n = 2.95 | int | 2 | int の 2 |
小数は int に入らないので、小数点以下は切り捨てられます。
一方、double 型変数 x なら…
| 代入式 | 左側の型 | 代入後の値 | 代入式の評価結果 |
|---|---|---|---|
| x = 2.95 | double | 2.95 | double の 2.95 |
この「代入式の評価結果」を利用すると、多重代入がスムーズに書ける、というわけです。
最大・最小を求める処理を“開いて”見るとこうなる
ループが苦手でも大丈夫。
DAYS が 7 のとき、max を求める部分は実質こういうことです。
max = steps[0];
if (steps[1] > max) max = steps[1];
if (steps[2] > max) max = steps[2];
...
if (steps[6] > max) max = steps[6];min も同じで、記号が逆になるだけ。
min = steps[0];
if (steps[1] < min) min = steps[1];
...だから「配列を走査しながら更新する」という感覚が掴めると、自然に書けるようになります。
登場した命令・演算子の書式と役割
#define 指令(オブジェクト形式マクロ)
書式
#define 名前 値何をする?
翻訳時に、名前を値へ置換します。今回なら DAYS を 7 に置換して、配列サイズやループ回数を一括管理できます。
for 文(配列走査)
書式
for (初期化; 条件式; 更新) {
繰り返す処理
}何をする?
添字 i を 0 から順に増やして、配列の要素を先頭から順番に処理します。
if 文(条件分岐)
書式
if (条件) 文;または
if (条件) {
文;
}何をする?
条件が真のときだけ処理を行います。max/min の更新に使います。
比較演算子 > と <
役割
- a > b:a が b より大きい
- a < b:a が b より小さい
代入演算子 =
役割
右辺の値を左辺へ入れます。代入式自体も「評価結果」を持つのがポイントです。
printf / scanf
printf 書式
printf(書式文字列, 値...);scanf 書式
scanf(書式文字列, 格納先アドレス);入力は配列要素なので、格納先は &steps[i] になります。
演習問題
演習5-4
配列の並びを反転するプログラムで、要素数をオブジェクト形式マクロで定義するように変更せよ。
また、交換回数の規則性(何回交換すれば良いか)を説明せよ。
解答例(要素数 N を使う版)
プロジェクト名:chap5-6-2 ソースファイル名:chap5-6-2.c
Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。
#include <stdio.h>
#define N 7
int main(void)
{
int x[N];
printf("%d個の整数を入力してください。\n", N);
for (int i = 0; i < N; i++) {
printf("x[%d]:", i);
scanf("%d", &x[i]);
}
for (int i = 0; i < N / 2; i++) { // 交換回数は N/2(整数の切り捨て)
int t = x[i];
x[i] = x[N - 1 - i];
x[N - 1 - i] = t;
}
puts("反転後の並びです。");
for (int i = 0; i < N; i++)
printf("x[%d] = %d\n", i, x[i]);
return 0;
}規則性の説明(ポイント)
- 先頭と末尾、次とその次…のように「左右ペア」で入れ替える。
- ちょうど半分まで交換すると反転が完成する。
- 交換回数は N/2(N が奇数なら真ん中は動かない)
演習5-5
a が double 型、b が int 型であるとする。次の代入のあと、a と b はどうなるか説明せよ。
a = b = 1.5;
解答例(説明)
- 右から評価されるので、まず b = 1.5 が実行される。
- b は int 型なので 1.5 は 1 に切り捨てられ、b は 1 になる。
- 代入式 b = 1.5 の評価結果は「代入後の b の値」で、int の 1
- 次に a = 1 が実行され、a は double 型なので 1.0 になる。
結果
| 変数 | 型 | 最終的な値 |
|---|---|---|
| b | int | 1 |
| a | double | 1.0 |
