閉じる

【C言語】fprintf()の使い方 ファイル出力のフォーマットを解説

ファイルに整った形でデータを書き出すには、標準出力向けのprintfだけでは不十分です。

fprintfは、同じ書式指定のまま、任意のファイルへ文字列を安全かつ柔軟に出力できる関数です。

本記事ではC言語初心者の方に向けて、基礎から実用的な書式指定、エラー処理まで丁寧に解説します。

fprintfの基本

fprintfとは

fprintfは、指定したファイルストリームに書式付きで文字列を出力する標準関数です。

書式指定はprintfと同じルールで扱えます。

関数プロトタイプ

C言語
int fprintf(FILE *stream, const char *format, ...);
  • 第1引数にはFILE*型のストリーム(例: fopenで開いたファイル)を渡します。
  • 第2引数は書式文字列、その後に書式に対応する値を並べます。
  • 戻り値は書き込んだ文字数、エラー時は負の値です。

printfとの違い

printfは標準出力(stdout)に書き出すのに対し、fprintfは任意のFILEに書き出します

つまり、出力先を自由に切り替えられます。

ログファイル、CSV、レポートなど、ファイル保存を伴う処理に向いています。

なおstderrなどの標準エラー出力もFILEであり、fprintf(stderr, ...)のように出力できます(標準入出力の詳細は別記事で扱います)。

使う場面

プログラムの実行結果を後から分析したい時、数値を決めた桁数でそろえたい時、CSVやTSVのような整形テキストを出力したい時に有用です。

フォーマット(書式)をコードで明示できるため、再現性の高い出力が得られます。

使い方の手順

ファイルを開く

まずfopenでファイルを開きます。

典型的には書き込み用に"w"または"a"を使います。

代表的なモードと意味

モード意味
“w”新規作成または既存ファイルを上書きして書き込み開始
“a”既存ファイルの末尾に追記、無ければ新規作成
“w+”読み書き両用。新規作成または上書き
“a+”読み書き両用。末尾に追記開始
“wb”/”ab”バイナリモードでの書き込み(改行の自動変換を抑制)

テキストファイルで通常は"w""a"を使います。

Windowsで改行コードの自動変換を避けたい場合は"wb"を使います。

書き込む

開いたFILE*に対してfprintfを呼ぶだけです。

書式文字列の中に%d%fなどの書式指定子を記述し、後ろに値を続けます。

改行やタブの指定

テキストの整形にはエスケープシーケンスを使います。

  • 改行: \n
  • タブ: \t

テキストファイルに対しては一般に\nを書けば十分です。

OSにより実ファイル上の改行コード表現は異なりますが、テキストモードではランタイムが適切に扱います。

ファイルを閉じる

書き込みが終わったらfcloseでファイルを閉じます。

バッファに溜まっているデータが確実にディスクへ書き出されます

途中で強制的に書き出したいときはfflush(fp)を用います。

以下は、タブ区切りの簡単なレポートを作成する例です。

C言語
#include <stdio.h>
#include <errno.h>
#include <string.h>

int main(void) {
    // ファイルを上書きモードで開く
    FILE *fp = fopen("report.txt", "w");
    if (fp == NULL) {
        // 開けない場合のエラー表示
        perror("fopen failed");
        return 1;
    }

    // 見出し行を書き込む(タブ区切り)
    // \t はタブ、\n は改行です
    if (fprintf(fp, "ID\tName\tScore\n") < 0) {
        perror("fprintf failed");
        fclose(fp);
        return 1;
    }

    // 3件のレコードを書き込む
    int id1 = 101, id2 = 102, id3 = 103;
    const char *name1 = "Alice";
    const char *name2 = "Bob";
    const char *name3 = "Carol";
    double score1 = 87.5, score2 = 92.0, score3 = 78.25;

    // %.2f は小数点以下2桁に丸めて表示します
    if (fprintf(fp, "%d\t%s\t%.2f\n", id1, name1, score1) < 0) {
        perror("fprintf failed");
        fclose(fp);
        return 1;
    }
    if (fprintf(fp, "%d\t%s\t%.2f\n", id2, name2, score2) < 0) {
        perror("fprintf failed");
        fclose(fp);
        return 1;
    }
    if (fprintf(fp, "%d\t%s\t%.2f\n", id3, name3, score3) < 0) {
        perror("fprintf failed");
        fclose(fp);
        return 1;
    }

    // 必要に応じて明示的にフラッシュ(通常は fclose で十分)
    if (fflush(fp) == EOF) {
        perror("fflush failed");
        fclose(fp);
        return 1;
    }

    // ファイルを閉じる
    if (fclose(fp) == EOF) {
        perror("fclose failed");
        return 1;
    }

    return 0;
}

実行結果出力ファイル(report.txt)の内容例
ID	Name	Score
101	Alice	87.50
102	Bob	92.00
103	Carol	78.25

fprintfは戻り値で成功・失敗を判定できます

上の例では、書き込みのたびに0未満かをチェックしています。

書式指定子の基礎

%d %f %s %cの使い方

基本的な書式指定子は次のとおりです。

型と書式は一致させることが重要です。

  • %d: 符号付き整数(int)
  • %f: 実数(double)。floatは可変長引数でdoubleに昇格します
  • %s: 文字列(charポインタ)
  • %c: 1文字(char)

桁幅と小数点の指定

数値や文字列をそろえたい場合は、桁幅(width)精度(precision)を使います。

  • %8d: 右寄せで最低8桁分を確保
  • %-8d: 左寄せで最低8桁
  • %08d: 空き部分を0で埋めて8桁
  • %.2f: 小数点以下2桁
  • %8.3f: 全体幅8、少数3桁、足りない部分は空白

文字列内の%を出す

%%と書くと、実際に%記号を1文字出力します。

fprintf(fp, "Progress: 50%%\n");

複数の値をまとめて出力

1回のfprintf呼び出しで複数の値を整形しながら一度に出力できます。

フォーマットと値の順序を合わせましょう。

以下は各書式指定子と桁幅・精度をまとめて確認する例です。

C言語
#include <stdio.h>

int main(void) {
    FILE *fp = fopen("format_demo.txt", "w");
    if (!fp) {
        perror("fopen failed");
        return 1;
    }

    int n = 123;
    double pi = 3.1415926535;
    const char *word = "hello";
    char ch = 'X';

    // 基本の出力
    fprintf(fp, "int: %d\n", n);
    fprintf(fp, "double: %f\n", pi);      // デフォルトは6桁表示
    fprintf(fp, "double(%.2f): %.2f\n", pi, pi); // 小数点以下2桁
    fprintf(fp, "string: %s\n", word);
    fprintf(fp, "char: %c\n", ch);

    // 桁幅・揃え・ゼロ埋め
    fprintf(fp, "right width: [%8d]\n", n);
    fprintf(fp, "left  width: [%-8d]\n", n);
    fprintf(fp, "zero pad   : [%08d]\n", n);

    // 浮動小数の幅と精度
    fprintf(fp, "float width.prec : [%8.3f]\n", pi);

    // 文字列内の % を出す
    fprintf(fp, "Progress: 50%% done.\n");

    // 複数値の同時出力
    fprintf(fp, "mix: id=%04d, name=%-8s, score=%.1f\n", 7, "Kai", 81.0);

    fclose(fp);
    return 0;
}

実行結果出力ファイル(format_demo.txt)の内容例
int: 123
double: 3.141593
double(%.2f): 3.14
string: hello
char: X
right width: [     123]
left  width: [123     ]
zero pad   : [00000123]
float width.prec : [   3.142]
Progress: 50% done.
mix: id=0007, name=Kai     , score=81.0

書式指定は「%[フラグ][幅][.精度][長さ]変換子」の順です。

初心者のうちは、-(左寄せ)、0(ゼロ埋め)、.精度から慣れていくと良いでしょう。

エラー処理と注意点

ファイルを開けない時の対処

fopenがNULLを返したら開けていません

原因はパスの間違い、権限不足、ディレクトリ未作成などが考えられます。

perrorstrerror(errno)で詳細を表示し、必要ならディレクトリ作成や権限の見直しを行います。

C言語
#include <stdio.h>
#include <errno.h>
#include <string.h>

FILE *open_report(const char *path) {
    FILE *fp = fopen(path, "w");
    if (!fp) {
        fprintf(stderr, "cannot open %s: %s\n", path, strerror(errno));
        return NULL;
    }
    return fp;
}

戻り値の確認

fprintfの戻り値は書き込んだ文字数、エラー時は負数です。

失敗時はferror(fp)が非0になっているかも確認できます。

C言語
int wrote = fprintf(fp, "value=%d\n", 42);
if (wrote < 0) {
    perror("fprintf failed");
    // 必要ならリカバリ処理
}

追記と上書きの違い

上書き(“w”)は既存内容を破棄、追記(“a”)は末尾に追加します。

ログや履歴は追記、結果ファイルの再生成は上書きを選びます。

目的推奨モード
ログを増やす“a”実行ごとに末尾へ追加
結果を作り直す“w”既存内容をすべて置き換える
読み書きテスト“w+” / “a+”書いた後に読み返すなど

バッファとfflushの基本

ファイルストリームは通常全バッファリングです。

fcloseで必ずフラッシュされます。

fflush(fp)途中経過をすぐディスクに反映したい時に使います。

毎回呼ぶと性能低下につながるため、必要なタイミングに限定しましょう。

なお標準出力は端末接続時に行バッファリングされますが、通常のファイルは改行で自動フラッシュされません

型と書式を合わせる

型と書式指定子が一致しないと未定義動作です。

以下を目安にしてください。

  • int%dunsigned int%u
  • long%ldlong long%lld
  • size_t%zu
  • double%f、指数表記は%e、汎用は%g
  • char *%schar%c

可変長引数ではfloatはdoubleに昇格するため、%.2ffloatを渡しても問題ありません。

一方、例:longに%dなどは危険です。

常に「変数の型」と「%の後の指定」を対応づけましょう。

まとめ

fprintfは「好きなファイルへprintfと同じ感覚で書式付き出力」できる強力な関数です。

使い方の基本は、ファイルをfopenで開き、fprintfで書き、必要ならfflushを行い、最後にfcloseで閉じるだけです。

%dや%fなどの書式指定子幅や精度の指定%%で%を出す方法を押さえれば、見やすいレポートやログ、CSVなどを簡単に生成できます。

さらに、戻り値やferrorでのエラー確認モード選択(上書き/追記)型と書式の一致を徹底することで、堅牢なファイル出力が実現します。

まずはサンプルを動かして、必要なフォーマットへ少しずつアレンジしてみてください。

この記事を書いた人
エーテリア編集部
エーテリア編集部

プログラミングの基礎をしっかり学びたい方向けに、C言語の基本文法から解説しています。ポインタやメモリ管理も少しずつ理解できるよう工夫しています。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!