つくる 配列で成績管理

人数を先に聞いてから、全員を配列に持つ

第4章の「つくる」では、N人ぶんの点数を入力しながらその場で足していきました。あのやり方では、入力が終わった時点で個々の点数は消えています。合計と平均は出せても、「最高点は何点か」には答えられませんでした。

配列を覚えた今なら、入力した点数を全部残しておけます。残っていれば、合計でも最高点でも、あとから何度でも数え直せます。これがこの章でいちばん大きな前進です。

大きめに確保して、使う数だけ回す

配列の個数は、コンパイル時に決まっている必要があります。人数は実行してから分かるので、先に十分な大きさを確保しておき、実際に使う数を変数で持ちます。

#define MAX_STUDENTS 100 int scores[MAX_STUDENTS]; int n; scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%d", &scores[i]); }

確保した数が 100 でも、ループは i < n で回します。i < MAX_STUDENTS にしてしまうと、入力していない箱まで読むことになり、中身の分からない値が集計に混ざります。

確保した大きさと、実際に使っている数は別という考え方は、前回の文字列でも出てきました。char 配列の箱の大きさと strlen の返す長さの関係とまったく同じです。C ではこの2つを自分で管理し続ける必要があります。

集計は入力とは別のループで

入力のループの中で合計や最高点を求めることもできますが、この章では役目ごとにループを分けます。

  1. 入力するループ
  2. 合計を出すループ
  3. 最高点を探すループ

分けておくと、あとから「最低点も出したい」となったときにループを1つ足すだけで済みます。データが配列に残っているからこそできる書き方です。

最高点の初期値は 0 ではなく scores[0] にします。今回の題材は点数なので 0 でも動いてしまいますが、その癖のままマイナスを含むデータを扱うと必ず事故ります。

平均は (double)total / n としてキャストを忘れないでください。n は入力から来る値なので、total / n と書くと切り捨てになります。

人数が0だとどうなるか

実務のコードなら、n が 0 のときの手当ても要ります。0 で割ると答えが定まらず、scores[0] も入力されていない箱を読むことになるからです。

if (n <= 0) { printf("データがありません\n"); return 0; }

第3章の分岐で、集計に入る前に弾いてしまうのが定石です。今回の課題では人数が1以上の入力しか来ませんが、こういう「起きたら困る入力」を先に潰しておく考え方は、章が進むほど効いてきます。同じ理由で、nMAX_STUDENTS を超えていないかも本来は確かめます。

この章を終えると、成績管理CLI は「人数を聞いて、全員ぶんを覚えて、何度でも数え直せる」ところまで来ます。あとは名前と点数をばらばらの配列で持つのをやめて、1人ぶんをひとまとまりにしたくなるはずです。それが第8章の構造体です。

では、第6章の総仕上げとして、人数ぶんの成績を配列で管理してみましょう。

要件

  1. 1つ目の入力が人数、続く入力が人数ぶんの点数
  2. 3人ぶんの点数を登録しました の形で人数を表示する
  3. 合計は237点です の形で合計を表示する
  4. 平均は79.0点です の形で、小数第1位まで表示する
  5. 最高点は92点です の形で最高点を表示する

入出力例

main("3", "80 65 92") → "3人ぶんの点数を登録しました 合計は237点です 平均は79.0点です 最高点は92点です" main("5", "60 70 80 90 100") → "5人ぶんの点数を登録しました 合計は400点です 平均は80.0点です 最高点は100点です"

ヒント

生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア
編集 LuaGate編集部
main.c
学習モード

メモ

つくる 配列で成績管理

⌘S で保存