コース一覧
    C言語基礎 ポインタ・構造体・ファイル
    ファイルの失敗に備える

    C言語基礎 ポインタ・構造体・ファイル

    C言語のポインタ、構造体、ファイル操作を学び、データを扱う基礎を固めるコースです。

    1
    ポインタの入口
    01. アドレスとは15分
    02. ポインタの&と*15分
    03. scanfの&の正体15分
    04. 関数で値を書き換える15分
    05. 配列を関数に渡す15分
    06. つくる 入力処理の関数化15分
    07. 第7章クイズ10分
    2
    構造体とファイル
    01. 構造体15分
    02. メンバの読み書き15分
    03. 構造体配列15分
    04. 構造体と関数15分
    05. ファイルに書き込む15分
    06. ファイルを読み込む15分
    07. ファイルの失敗に備える15分
    08. つくる 保存機能15分
    09. 第8章クイズ10分
    3
    総合制作
    01. メニュー統合15分
    02. 自由拡張15分
    03. 完成と次のステップ10分

    ファイルの失敗に備える

    初回起動でいきなり落ちる

    前回作った読み込み処理には、まだ大きな穴があります。成績管理CLI を初めて起動したとき、scores.txt はまだ存在しません。存在しないファイルを "r" で開こうとすると、fopen は失敗します。

    このとき fopen は NULL を返します。NULL は「どこも指していない」ことを表す特別なポインタの値でした。第7章で出てきた「住所を入れる変数」に、有効な住所が入らなかった状態です。

    問題は、その NULL を確かめずに fscanf(fp, ...) を呼んでしまうことです。存在しない場所を読みに行くので、プログラムはその場で異常終了します。コンパイルは通るので、実際に動かすまで気づけません。

    開いた直後に必ず確かめる

    対策はいたって単純で、開いた直後に NULL かどうか見るだけです。

    c

    fp = fopen("scores.txt", "r");
    if (fp == NULL) {
        printf("保存データがありません\n");
    } else {
        /* ここで読む */
        fclose(fp);
    }

    大事なのは、NULL は必ずしも異常ではないという点です。初回起動でファイルが無いのは当たり前のことで、そのときは「0 人からはじめる」と決めておけばよいだけです。エラーで止めるのか、無かったことにして進めるのかは、プログラムを書く側が決めます。

    失敗が起こる理由はほかにもあります。読もうとしたものがディレクトリだった、権限が無くて読めない、書き込み先のディスクがいっぱい、といったものです。"w" で開くときも失敗しうるので、書き込み側も同じように確かめます。

    閉じるのは開けたときだけ

    もうひとつ気をつける点があります。fclose に NULL を渡してはいけません。開けなかったのに閉じようとするのは、持っていない鍵で鍵をかけるようなものです。上の例で fclose を else の中に置いているのはそのためです。

    また、return 1; で終わらせる形もよく使われます。main が返す 0 以外の値は「異常終了した」という合図で、あとで他のプログラムと組み合わせるときに効いてきます。読み込みに失敗しただけなら続けてよくても、保存に失敗したまま「保存しました」と表示するのは嘘になるので、書き込み側は止めるほうが親切です。

    等号を1つにしない

    if (fp == NULL) の == を 1 つにして if (fp = NULL) と書くと、比較ではなく代入になります。fp が NULL で上書きされたうえ、条件は必ず偽になるので、チェックが素通りしたまま次の行で異常終了します。第3章でも出てきた間違いですが、ポインタが相手だと被害が大きくなります。

    今回は、確実に存在しない missing.txt を開いて NULL が返るのを確かめてから、scores.txt に書いて読み直すところまで通します。

    要件

    1. missing.txt を読み込みモードで開き、NULL なら「missing.txt は開けませんでした」と表示する
    2. scores.txt を書き込みモードで開き、NULL なら「保存に失敗しました」と表示して return 1 で終わる
    3. scores.txt を読み込みモードで開き、NULL なら「読み込みに失敗しました」と表示して return 1 で終わる
    4. 読み直した内容を「田中さんの82点を保存しました」の形で表示する

    ヒント

    比較は if (fp == NULL) です。= を1つにすると代入になってしまいます

    fclose を呼ぶのは開けたときだけです

    missing.txt はどこにも作らないので、必ず NULL が返ります

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

    関連レッスン

    • つくる 保存機能

      読み込みから更新、保存までを1本で通せるようになります。

    • 第8章クイズ

      第8章の理解を確認します。

    • メニュー統合

      登録と一覧と集計と保存をメニュー式の1本にまとめられるようになります。

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

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

    • 処理計算や代入を表す長方形
    • 変数データに名前をつけて参照する仕組み
    • コンパイルソースをバイトコードへ変換する処理
    • ディレクトリファイルを整理するフォルダのこと。
    main.c
    エディタを読み込んでいます

    メモ

    ファイルの失敗に備える

    ⌘S で保存