集計
合計は「入れ物を先に用意する」
配列を最後まで回せるようになったので、集計に進みます。合計を出すときの型は毎回同じです。
int total = 0;
for (int i = 0; i < SUBJECTS; i++) {
total += scores[i];
}先に total を 0 にしておき、ループで1つずつ足していきます。これを 累積 と言います。大事なのは、total = 0; を ループの外 に書くことです。中に書くと毎回 0 に戻ってしまい、最後の1科目ぶんしか残りません。
初期値を書かずに int total; とだけ宣言するのも駄目です。前回話したとおり、中身が何か分からない状態から足し算を始めることになり、実行するたびに違う答えが出ます。
平均はキャストを忘れない
第2章でやった整数どうしの割り算の罠が、ここでも出ます。
int total = 369;
printf("%d\n", total / 5); // 73 になる。小数が消える
printf("%.1f\n", (double)total / 5); // 73.8total / 5 は int どうしの割り算なので、73.8 の小数部分が切り捨てられて 73 になります。片方を (double) にすると、もう片方も自動で double に合わせられ、小数のまま計算されます。
表示にも注意が必要です。%f をそのまま使うと 73.800000 と小数6桁で出ます。点数の平均なら %.1f のように桁を決めて出すほうが読みやすくなります。
途中結果を持ち回る利点
合計を変数に持っておくと、平均だけでなく、あとから「平均より高い科目はどれか」といった処理にも使い回せます。
for (int i = 0; i < SUBJECTS; i++) {
if (scores[i] * SUBJECTS > total) {
printf("%d科目目は平均より上です\n", i + 1);
}
}ここでは scores[i] > total / SUBJECTS ではなく、両辺に SUBJECTS を掛けた形で比べています。割り算の切り捨てを避けるための小技で、全部 int のまま正確に比べられます。こういう書き換えができるのも、合計を捨てずに持っているおかげです。
配列とループと累積の3つがそろうと、「データを集めて数える」というプログラムの基本形が書けるようになります。成績管理CLI もここから一気に実用的になります。
では、5科目の合計と平均を出してみましょう。
要件
- 5つの整数を配列に読み込む
- 合計は 合計は369点です の形で出す
- 平均は 平均は73.8点です の形で、小数第1位まで出す
入出力例
main("80 65 92 74 58") → "合計は369点です
平均は73.8点です"
main("60 70 80 90 100") → "合計は400点です
平均は80.0点です"