つくる 保存機能

章の総仕上げ

この章で覚えたことを 1 本につなぎます。構造体で名前と点数をまとめ、配列で人数分持ち、ファイルに保存して読み戻し、開けなかったときに備える。成績管理CLI に「前回の続き」が生まれる回です。

保存と読み込みを関数にする

ファイル操作は行数が多く、main に直接書くと本筋が埋もれます。第5章で学んだとおり、まとまりごとに関数へ追い出します。

int load_students(struct Student list[]) { FILE *fp; int count = 0; fp = fopen("scores.txt", "r"); if (fp == NULL) { return 0; } while (count < MAX && fscanf(fp, "%31s %d", list[count].name, &list[count].score) == 2) { count = count + 1; } fclose(fp); return count; }

読み込む関数は 人数を返す 形にします。ファイルが無ければ 0 を返すので、初回起動でも呼び出し側は何も特別扱いしなくて済みます。if (fp == NULL) return 0; の 1 行が、前回学んだ備えです。

引数の struct Student list[] は、第7章でやった配列引数です。配列は先頭のアドレスが渡るので、関数の中で書き込んだ結果はそのまま呼び出し元の配列に残ります。構造体を 1 個だけ渡すときと違い、コピーは作られません。

保存側も同じ形です。書き込みモードの "w" は既存の中身を消してから開くので、「今メモリにある全員をそのまま書き直す」という単純な作りにできます。1 人追加するたびに全部書き直すのは無駄に見えますが、数十人の成績表ならこれで十分です。

順番を決める

通しの流れは、読み込む・変える・保存する、の 3 段階です。今回は次の順で動かします。

  1. 入力された人数と全員の名前・点数、そして全員に足す点数を読む
  2. いったん保存して、保存済みデータがある状態を作る
  3. 読み戻して件数を表示する
  4. 全員に加点して、また保存する
  5. もう一度読み戻して一覧と平均を出す

2 と 3 をわざと分けているのは、保存したものが本当に読み戻せているかを、目で確かめるためです。書けたつもりで fclose を忘れていると、ここで件数が 0 になって一発で分かります。

1回の実行で完結させる理由

本物のアプリなら、保存は今日の実行、読み込みは明日の実行、と別々に起こります。ただ練習では、前に動かしたときのファイルが残っているとは限らず、残っていたら残っていたで結果が変わってしまいます。書いてから読む形にしておけば、何度実行しても同じ結果になります。

ここまで通れば、成績管理CLI は「終了しても成績が消えない」プログラムになりました。次の章では、これまでに作った登録・一覧・集計・保存をメニューから選べる 1 本にまとめます。

要件

  1. load_students は scores.txt を読み、読めた人数を返す。ファイルが無ければ0を返す
  2. save_students は list の先頭 count 人を scores.txt に書き出す
  3. 保存して読み戻したあと「3件読み込みました」の形で件数を表示する
  4. 全員に加点して保存し直し、読み戻した一覧を「田中 87点」の形で表示する
  5. 最後に「平均は86点です」の形で平均を表示する

入出力例

main("3", "田中 82", "佐藤 90", "鈴木 71", "5") → "3件読み込みました 田中 87佐藤 95鈴木 76平均は86点です" main("2", "高橋 60", "伊藤 70", "10") → "2件読み込みました 高橋 70伊藤 80平均は75点です"

ヒント

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

メモ

つくる 保存機能

⌘S で保存