【C言語入門】テキストファイルの読み込みと書き出し!fgetc/fputc, fgets/fputsを完全解説

プログラムが終了してもデータを保存しておきたい、設定ファイルを読み込みたい、実行結果をログとして残したい──。こうした要望を叶えるのがファイル入出力の機能です。C言語には、テキストファイルを扱うための基本的で強力な関数が多数用意されています。

この記事では、C言語におけるテキストファイルの読み書きの基本となる**fopen**, **fclose**から、1文字ずつ、そして1行ずつファイルを操作する関数までを、分かりやすく解説します。


目次

ファイル操作の第一歩:fopenfclose

ファイル操作を行うには、まず目的のファイルを「開く」必要があります。そして、作業が終わったら必ず「閉じる」のが作法です。

  • FILE *fopen(const char *filename, const char *mode);
    • ファイルを指定したモードで開き、ファイルを操作するためのファイルポインタ (FILE *) を返します。
    • 失敗した場合は NULL を返します。fopenの後のNULLチェックは必須です。
  • int fclose(FILE *fp);
    • 開いたファイルを閉じます。これにより、書き込んだ内容がディスクに保存され、OSのリソースが解放されます。

主なファイルオープンモード

モード説明ファイルが存在しない場合ファイルが存在する場合
"r"読み込み専用 (Read)エラーになる先頭から読み込む
"w"書き込み専用 (Write)新規作成する内容が上書き消去される
"a"追記専用 (Append)新規作成する末尾に追記する

1文字単位の入出力:fgetcfputc

ファイルを1文字ずつ、きめ細かく読み書きしたい場合に使うのが fgetcfputc です。

  • int fgetc(FILE *fp);: ファイルから1文字読み込み、その文字コードを返します。ファイルの終端に達した場合やエラー時には EOF という特別な値を返します。
  • int fputc(int character, FILE *fp);: ファイルに1文字書き込みます。

実践例:ファイルのコピープログラム(1文字ずつ)

source.txt の内容を destination.txt に1文字ずつコピーするプログラムです。

#include <stdio.h>

int main(void) {
    FILE *source_fp, *dest_fp;
    int ch; // fgetcの戻り値がEOF(-1)の可能性があるため、int型で受け取る

    // 読み込みファイルを開く
    if ((source_fp = fopen("source.txt", "r")) == NULL) {
        printf("読み込みファイルのオープンに失敗しました。\n");
        return 1;
    }
    // 書き出しファイルを開く
    if ((dest_fp = fopen("destination.txt", "w")) == NULL) {
        printf("書き出しファイルのオープンに失敗しました。\n");
        fclose(source_fp); // 開いたファイルを閉じる
        return 1;
    }

    // 1文字読み込み、EOFでなければ、その文字を書き出すループ
    while ((ch = fgetc(source_fp)) != EOF) {
        fputc(ch, dest_fp);
    }

    printf("ファイルのコピーが完了しました。\n");

    // ファイルを閉じる
    fclose(dest_fp);
    fclose(source_fp);

    return 0;
}

1行単位の入出力:fgetsfputs

ログファイルのように、改行で区切られたテキストを効率的に扱いたい場合は fgetsfputs を使います。

  • char *fgets(char *str, int n, FILE *fp);: ファイルから最大n-1文字、または改行までを1行として読み込み、文字列strに格納します。読み込みに成功すればstrを、ファイルの終端やエラー時には NULL を返します。
  • int fputs(const char *str, FILE *fp);: ファイルに文字列strを書き込みます。fgetsと違い、自動で改行は追加されません。

実践例:ファイルのコピープログラム(1行ずつ)

1文字ずつのコピーよりも効率的な方法です。

#include <stdio.h>

#define LINE_BUFFER_SIZE 256

int main(void) {
    FILE *source_fp, *dest_fp;
    char line_buffer[LINE_BUFFER_SIZE];

    if ((source_fp = fopen("source.txt", "r")) == NULL) {
        printf("読み込みファイルのオープンに失敗しました。\n");
        return 1;
    }
    if ((dest_fp = fopen("destination.txt", "w")) == NULL) {
        printf("書き出しファイルのオープンに失敗しました。\n");
        fclose(source_fp);
        return 1;
    }

    // 1行読み込み、NULLでなければ、その行を書き出すループ
    while (fgets(line_buffer, LINE_BUFFER_SIZE, source_fp) != NULL) {
        fputs(line_buffer, dest_fp);
    }

    printf("ファイルのコピーが完了しました。\n");
    
    fclose(dest_fp);
    fclose(source_fp);

    return 0;
}

おまけ:書式付き入出力 fprintffscanf

printfscanfと同じように、書式を指定してファイルに書き込んだり、読み込んだりすることもできます。CSVファイルのような、構造化されたテキストデータを扱う際に非常に便利です。

  • int fprintf(FILE *fp, const char *format, ...);: printfのファイル版。
  • int fscanf(FILE *fp, const char *format, ...);: scanfのファイル版。

実践例:スコアデータをファイルに記録・読み込み

#include <stdio.h>

int main(void) {
    FILE *fp;
    char name[50];
    int score;

    // --- 書き込み ---
    if ((fp = fopen("scores.txt", "w")) == NULL) { return 1; }
    fprintf(fp, "Player1 1500\n");
    fprintf(fp, "Player2 2300\n");
    fclose(fp);
    printf("スコアを scores.txt に書き込みました。\n\n");

    // --- 読み込み ---
    if ((fp = fopen("scores.txt", "r")) == NULL) { return 1; }
    printf("スコアを読み込みます:\n");
    // ファイルの終わりまで書式付きで読み込む
    while (fscanf(fp, "%s %d", name, &score) != EOF) {
        printf("名前: %s, スコア: %d\n", name, score);
    }
    fclose(fp);

    return 0;
}

実行結果:

スコアを scores.txt に書き込みました。

スコアを読み込みます:
名前: Player1, スコア: 1500
名前: Player2, スコア: 2300

まとめ

C言語のテキストファイル操作は、プログラムの可能性を大きく広げます。

関数ペア単位用途
fgetc / fputc1文字最も基本的。文字単位での細かな処理に。
fgets / fputs1行(文字列)効率的。ログファイルや設定ファイルの扱いに最適。
fscanf / fprintf書式付きCSVのような構造化データを扱う場合に強力。

Google スプレッドシートにエクスポート

どの方法を使うにせよ、fopenで開き、②処理を行い、③fcloseで閉じるという流れは同じです。この基本をマスターして、データの永続化に挑戦してみましょう!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次