コース一覧
    C言語中級 連結リスト・応用
    自由拡張

    C言語中級 連結リスト・応用

    C言語の連結リストと応用的なデータ操作を学び、実装でデータを扱うコースです。

    1
    連結リスト
    01. 配列の限界15分
    02. ノードを定義する15分
    03. 先頭に追加する15分
    04. リストを歩く15分
    05. 任意位置の挿入と削除15分
    06. リストを全解放する15分
    07. つくる リスト版成績管理15分
    08. 第5章クイズ10分
    2
    応用
    01. 動的な二次元配列15分
    02. コマンドライン引数15分
    03. バイナリ保存15分
    04. エラーの調べ方15分
    05. つくる 引数とバイナリ保存15分
    06. 第6章クイズ10分
    3
    総合制作
    01. リスト版を完成させる20分
    02. メモリバグ演習20分
    03. 自由拡張20分
    04. 完成と次のステップ10分

    自由拡張

    足す前に仕様を決める

    ここまでで成績管理CLI のリスト版は一通り動くようになりました。ここからが本当の制作です。使ってみて足りないと思った機能を、自分で足します。

    好きに作ってよいと言われて手が止まる人は多いはずです。理由ははっきりしていて、どこまでできれば完成なのかが決まっていない からです。書く前に決めることは 3 つあります。何を入力するか、何を出力するか、うまくいかなかったときどうするか。この 3 つが決まれば、あとは書くだけの作業になります。今回はその練習として、2 つの機能を仕様つきで用意しました。順位表と、平均以上の抽出です。

    順位表はポインタの配列を作って並べる

    リストは並べ替えが苦手です。ノードの next を付け替えて順序を変えることもできますが、登録順という情報が壊れてしまいます。楽なのは、ノードを指すポインタだけを集めた配列 を作り、その配列を並べ替える方法です。

    c

    struct Node **arr = malloc(count * sizeof(struct Node *));

    struct Node ** は「struct Node へのポインタ」を指すポインタです。中身はノードの複製ではなく番地なので、いくら並べ替えてもリスト本体の next は 1 つも変わりません。表示が終わったら配列だけを解放します。ノードは解放しません。借りた配列の持ち主はこの関数ですが、ノードの持ち主はリストのままだからです。

    並べ替えは第4章の qsort を使います。要素がポインタなので、比較関数に渡ってくるのは struct Node * を指すポインタ、つまり struct Node ** です。*(struct Node **)a と 1 段はがしてからメンバを読みます。

    同点の順番は自分で決める

    qsort は同点のときにどちらを前に置くか保証しません。手元で正しく見えても、別の環境では入れ替わることがあります。ですから 2 番目のキーまで決めて、順序が一意になるようにします。今回はノードに登録番号 id を持たせて、点数が同じなら id の小さいほうを上にします。

    借りたものと借りていないもの

    この回でいちばん間違えやすいのは、順位表を出したあとの後始末です。この関数の中で malloc したのは配列 1 本だけなので、返すのも配列 1 本だけです。配列の中に入っているのはノードの番地ですが、そのノードを作ったのはこの関数ではありません。リストがまだ使っているものを勝手に解放すれば、そのあとの一覧表示で解放済みの領域を読むことになります。

    その領域を確保した人が解放する という持ち主の考え方を、ここで一度はっきりさせておきます。関数を書くときは、返す義務があるのはどれかを最初に決めます。決めておけば、あとから読む人も迷いません。

    平均以上は割り算しないで比べる

    平均以上の学生を選ぶとき、平均を double で求めてから比べたくなりますが、割り算をすると端数が出ます。score >= (double)total / count は多くの場合正しく動きますが、両辺に count を掛けた score * count >= total なら整数のままで、端数の心配がありません。表示のときだけ %.1f で小数にします。

    要件

    1. 1 から 4 と 0 の動きは前回と同じ。starterCode に入っているので変えない
    2. 5 は点数の高い順に「1位 鈴木 95点」の形で全員を出す。0人なら「学生がいません」
    3. 5 で同点になったときは、登録が早いほう、つまり id の小さいほうを上にする
    4. 5 のあとで 2 の一覧を出しても、並びは登録順のままにする
    5. 5 で確保した作業用の配列は、表示が終わったら解放する。ノードは解放しない
    6. 6 は1行目に「平均は81.7点です」を出し、続けて平均以上の学生を登録順に「鈴木 95点」の形で出す。0人なら「学生がいません」
    7. 終了時は全ノードを解放し、「3件解放しました」「終了します」の2行を出す
    8. 入力をうながす案内文は一切出さない

    ヒント

    並べ替える配列の要素はノードそのものではなくノードを指すポインタです。malloc(count * sizeof(struct Node *)) で確保します

    比較関数に渡ってくるのは要素を指すポインタなので、*(struct Node **)a と1段はがしてから score や id を読みます

    平均以上の判定は score * count >= total と書くと、割り算の端数を気にせずに済みます

    生田 陸人
    監修生田 陸人
    ゆめさくエンジニア / 現役ソフトウェアエンジニア監修者プロフィールを見る →
    編集 ゆめさく編集部·公開 2026/08/07

    関連レッスン

    • 完成と次のステップ

      次に何を学ぶかを選べるようになります。

    • メモリバグ演習

      リーク・二重解放・ダングリングを見つけて直せるようになります。

    • リスト版を完成させる

      全機能をリスト前提で1本にまとめられるようになります。

    このレッスンに出てくる用語

    意味があいまいなまま進んだ語は、ここから読み直せます。

    • リスト順序付きで複数の値を扱うデータ構造
    • 配列サイズ固定の同型データの集まり
    • 関数処理に名前を付けて再利用できる単位
    main.c
    エディタを読み込んでいます

    メモ

    自由拡張

    ⌘S で保存