メニュー統合

8章ぶんの部品を1本につなぐ

前回まででバラバラに書いてきた部品が、これで揃いました。第6章の配列、第8章の構造体、第5章の関数、第4章のループ、第3章の分岐、そして第8章のファイル保存です。今回はそれらを 1 つの main の下にまとめて、番号を打つと処理が選べる メニュー方式 の成績管理CLIにします。

メニュー方式の骨は、第4章でやった「条件を満たす間くり返す」だけです。番号を 1 つ読む、その番号で処理を選ぶ、また番号を読む。終了番号が来たらループを抜ける。それだけです。

while (scanf("%d", &command) == 1 && command != 0) { if (command == 1) { /* 登録 */ } else if (command == 2) { /* 一覧 */ } }

scanf の戻り値は 読み取れた項目の数 です。入力が尽きると 1 より小さい値が返るので、== 1 を条件に入れておくと、入力が終わったときも無限ループにならずに止まります。

処理は関数に、データは構造体配列に

if の中に処理を直接書いていくと、main があっという間に読めない長さになります。第5章でやったとおり、まとまった仕事は関数に切り出します。一覧表示なら show_all、集計なら show_summary、保存なら save_all という具合です。こうすると main は「番号を読んで、対応する関数を呼ぶだけ」になり、全体の流れが数行で見渡せます。

渡すデータは Student の配列と、いま何人入っているかを表す count の 2 つです。配列は関数に渡すと先頭アドレスが渡るので、関数側で書き換えた内容は呼び出し元にも残ります。第7章で確かめた性質がそのまま効いています。

画面に出す文字は仕様として決める

このコースの採点は、標準入力を流して標準出力を突き合わせる形です。そのため 入力をうながす案内文は出しません。番号や名前を打ってくださいという文言を出すと、それも出力の一部として比較されてしまうからです。

実務では案内文を出したほうが親切ですが、自動テストにかける部分と、人に見せる部分を分けて考えるのは実務でも同じです。まずは出力仕様を厳密に決め、そのとおりに動くことを機械で確かめる。案内文は最後に printf を足せば済みます。

一気に完成させようとしない

まとめる作業でつまずく人の多くは、全部書いてから一度にコンパイルします。そうすると 20 個のエラーが同時に出て、どれが本当の原因か分からなくなります。

順番はこうです。まず番号を読んで終了だけできるループを完成させ、動かします。次に登録を足して動かします。次に一覧、次に集計、最後に保存です。1 つ足すごとにコンパイルして走らせれば、エラーが出ても原因はいま書いた数行の中にしかありません。第1章でコンパイルエラーの読み方をやったのは、この場面のためでもあります。

小さく動かして少しずつ育てるやり方は、このあと何を書くときにも効きます。では、成績管理CLI を完成させましょう。

要件

  1. Student 構造体 (char name[32] と int score) と、その配列で最大10人まで持つ
  2. 番号を1つ読み、1 なら登録、2 なら一覧、3 なら集計、4 なら保存、0 なら終了する
  3. 1 は続けて名前と点数を読み、「田中を登録しました」の形で出す
  4. 2 は登録順に「田中 80点」の形で1行ずつ出す。0人なら「学生がいません」
  5. 3 は「人数は3人です」「合計は245点です」「平均は81.7点です」の3行を出す。平均は %.1f。0人なら「学生がいません」
  6. 4 は scores.txt に書き出し、「3件保存しました」と出す
  7. 1〜4 と 0 以外の番号は「その番号はありません」と出す
  8. ループを抜けたら最後に「終了します」と出す
  9. 入力をうながす案内文は一切出さない

入出力例

main("1 田中 80 1 鈴木 70 1 佐藤 95 2 3 4 0 ") → "田中を登録しました 鈴木を登録しました 佐藤を登録しました 田中 80鈴木 70佐藤 95人数は3人です 合計は245点です 平均は81.7点です 3件保存しました 終了します" main("2 3 9 0 ") → "学生がいません 学生がいません その番号はありません 終了します" main("1 田中 70 1 鈴木 75 3 0 ") → "田中を登録しました 鈴木を登録しました 人数は2人です 合計は145点です 平均は72.5点です 終了します"

ヒント

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

メモ

メニュー統合

⌘S で保存