つくる N人分の入力
3人固定から、N人へ
第2章のつくる回では、3 科目ぶんの点数を入力して平均を出しました。あのプログラムは scanf を 3 回並べて書いていたので、4 人になった瞬間に書き直しが必要でした。この章でループを覚えたので、いよいよ 人数を実行時に決められる 形にします。
組み立ては 3 つの部品でできています。
- 人数を 1 回だけ読む
- その回数だけループを回し、中で 1 人ぶんの点数を読んで合計に足す
- ループを抜けてから、合計と平均を出す
変数はループの外に置く
いちばん間違えやすいのが、合計を入れる変数の置き場所です。
int total = 0;
for (i = 1; i <= n; i++) {
scanf("%d", &score);
total += score;
}total は全員ぶんを積み上げる箱なので、ループの 外 で 1 回だけ 0 にします。ループの中で int total = 0; と書くと、毎回作り直されて 0 に戻り、最後の 1 人ぶんしか残りません。一方 score は 1 人ぶんの一時的な値なので、毎回上書きされてかまいません。この「積み上げる変数」と「使い捨ての変数」の区別は、次章以降もずっと出てきます。
人数ぶんの点数を保管しておく方法はまだ習っていないので、読んだ点数はその場で合計に足して捨てます。全員の点数をあとから見返せるようにするのは、第6章の配列の仕事です。
平均で切り捨てないために
第2章で見たとおり、int どうしの割り算は小数が切り捨てられます。240 を 3 で割ると 80 ですが、250 を 3 で割ると 83 になり、正しい 83.33 が消えます。
double average = (double)total / n;
printf("平均は%.1f点です\n", average);片方を double にキャストすれば、割り算そのものが小数の計算になります。表示のときは %f のままだと小数第 6 位まで出てしまうので、%.1f と桁を指定します。
入力を促すメッセージも忘れずに出してください。何も表示せずに入力待ちになるプログラムは、使う人から見ると固まったのと区別が付きません。今回は「1人目の点数」のように何人目かを添えるので、printf の中でループ変数 i をそのまま使えます。
この章でできるようになったこと
第3章までのプログラムは、書いた時点で処理の回数が決まっていました。この章のループを手に入れたことで、実行してみるまで分からない量のデータを扱えるようになりました。人数が 3 人でも 40 人でも、コードは 1 文字も変わりません。これは繰り返しがもたらす、いちばん大きな変化です。
残っている弱点は、読んだ点数をその場で捨てていることです。合計は出せても、あとから「2 人目は何点だったか」を聞かれると答えられませんし、最高点を探すこともできません。値をまとめて持っておく道具が配列で、第6章で扱います。次章ではその前に、長くなってきた main を切り分けるための関数を学びます。
では、人数を聞いて、その人数ぶんの点数を集計する成績管理CLI を書きましょう。
要件
- 最初に「人数を入力してください」と表示して人数を読む
- 点数を読む前に「1人目の点数」の形で何人目かを表示する
- 合計は「合計は240点です」の形で表示する
- 平均は「平均は80.0点です」の形で、小数第1位まで表示する
- 人数は1以上が入力される前提でよい
入出力例
main(3, 80, 90, 70) → "人数を入力してください
1人目の点数
2人目の点数
3人目の点数
合計は240点です
平均は80.0点です"
main(4, 100, 85, 60, 55) → "人数を入力してください
1人目の点数
2人目の点数
3人目の点数
4人目の点数
合計は300点です
平均は75.0点です"
main(3, 80, 85, 85) → "人数を入力してください
1人目の点数
2人目の点数
3人目の点数
合計は250点です
平均は83.3点です"