C言語プログラミング:fputs 関数で実現するファイル入出力の多様な活用例


構文

int fputs(const char *str, FILE *stream);

引数

  • stream: 出力先のファイルストリームを指す FILE 構造体ポインタ
  • str: 出力する文字列を含む NULL 文字で終端された文字列ポインタ

戻り値

正常に動作した場合、fputs 関数は書き込まれたバイト数を返します。エラーが発生した場合、EOF を返します。

詳細

  • バイナリモードで開かれているストリームに fputs 関数を使用すると、予期しない結果が生じる可能性があります。
  • fputs 関数は、ストリームがテキストモードで開かれている場合、出力される文字列の末尾に改行 (\n) 文字を追加しません。
  • エラーが発生した場合、stream のエラーインジケータが設定されます。
  • NULL 文字 (\0) は書き込まれません。
  • fputs 関数は、文字列 str の各文字を順番に stream に書き込みます。


#include <stdio.h>

int main() {
  FILE *fp;

  fp = fopen("test.txt", "w");
  if (fp == NULL) {
    perror("fopen failed");
    exit(1);
  }

  fputs("Hello, world!\n", fp);

  fclose(fp);

  return 0;
}

この例では、fputs 関数は "Hello, world!" という文字列を "test.txt" というファイルに出力します。

  • ファイル入出力に関する詳細については、C言語の標準ライブラリのマニュアルを参照してください。
  • より複雑なファイル入出力操作には、fprintf 関数や fwrite 関数などの他の関数を使用することが推奨されます。
  • fputs 関数は、比較的単純なファイル出力タスクに使用されます。

fputs 関数の利点

  • 改行 (\n) 文字を自動的に追加しない(テキストモードの場合)
  • NULL 文字 (\0) を自動的に処理する
  • シンプルで使いやすい

fputs 関数の欠点

  • エラー処理が限定的
  • フォーマットされた出力には対応していない
  • バイナリモードでの使用には適していない
  • より高度なファイル入出力操作が必要な場合は、fopenfclosefreadfseek などの他のファイル入出力関数と組み合わせて使用します。
  • バイナリデータを書き込む必要がある場合は、fwrite 関数を使用します。
  • フォーマットされた出力を必要とする場合は、fprintf 関数を使用します。


ファイルへの単純な文字列出力

#include <stdio.h>

int main() {
  FILE *fp;

  fp = fopen("test.txt", "w");
  if (fp == NULL) {
    perror("fopen failed");
    exit(1);
  }

  fputs("Hello, world!\n", fp);
  fputs("This is another line.\n", fp);

  fclose(fp);

  return 0;
}

このコードは、"test.txt" というファイルに "Hello, world!" と "This is another line." という 2 つの行を出力します。

エラー処理

#include <stdio.h>

int main() {
  FILE *fp;

  fp = fopen("nonexistent.txt", "w");
  if (fp == NULL) {
    perror("fopen failed");
    exit(1);
  }

  fputs("This will not be written.\n", fp);

  fclose(fp);

  return 0;
}

このコードは、存在しないファイル "nonexistent.txt" を開こうとします。ファイルが開けないため、fopen 関数は NULL を返し、perror 関数はエラーメッセージを出力します。

バイナリモードでの使用

#include <stdio.h>

int main() {
  FILE *fp;
  char data[] = {0x61, 0x62, 0x63, 0x64, 0x65};

  fp = fopen("binary.data", "wb");
  if (fp == NULL) {
    perror("fopen failed");
    exit(1);
  }

  fputs("This will not be written correctly.\n", fp);  // エラーが発生する

  fwrite(data, sizeof(data), 1, fp);

  fclose(fp);

  return 0;
}

このコードは、"binary.data" というバイナリファイルを開き、data 配列の内容を書き込みます。しかし、fputs 関数はテキストモードで動作するため、バイナリデータとして正しく書き込まれません。バイナリデータを書き込むには、fwrite 関数を使用する必要があります。

#include <stdio.h>

int main() {
  FILE *fp;

  fp = fopen("test.txt", "w");
  if (fp == NULL) {
    perror("fopen failed");
    exit(1);
  }

  fputs("Hello, %s!\n", fp);  // フォーマットを使用できない

  fprintf(fp, "Goodbye, %s!\n", "world");  // フォーマットを使用できる

  fclose(fp);

  return 0;
}


以下に、いくつかの代替手段とその利点と欠点を示します。

fprintf 関数

  • 欠点:
    • fputs 関数よりも少し複雑
    • NULL 文字 (\0) を自動的に処理しない
  • 利点:
    • フォーマットされた文字列出力が可能
    • 変数や式を文字列に埋め込むことができる
    • エラー処理が容易


#include <stdio.h>

int main() {
  FILE *fp;
  int age = 25;

  fp = fopen("test.txt", "w");
  if (fp == NULL) {
    perror("fopen failed");
    exit(1);
  }

  fprintf(fp, "Hello, world! I am %d years old.\n", age);

  fclose(fp);

  return 0;
}

fwrite 関数

  • 欠点:
    • 文字列データの書き込みには fputsfprintf 関数よりも複雑
    • フォーマットされた出力には対応していない
  • 利点:
    • バイナリデータの書き込みに適している
    • 構造体や配列などの複雑なデータを書き込むことができる


#include <stdio.h>

int main() {
  FILE *fp;
  struct person {
    char name[32];
    int age;
  };

  struct person p = {"Alice", 30};

  fp = fopen("data.bin", "wb");
  if (fp == NULL) {
    perror("fopen failed");
    exit(1);
  }

  fwrite(&p, sizeof(struct person), 1, fp);

  fclose(fp);

  return 0;
}
  • fopenfclosefreadfseek などの関数を使用して、より高度なファイル入出力操作を組み立てることができます。
  • fputs 関数は、フォーマットされた出力には対応していません。フォーマットされた出力を必要とする場合は、fprintf 関数を使用してください。
  • fputs 関数は、NULL 文字 (\0) を自動的に処理します。文字列に NULL 文字を含める必要がある場合は、fprintf 関数または fwrite 関数を使用する必要があります。
  • fputs 関数は、テキストモードで開かれているファイルにのみ使用してください。バイナリモードで開かれているファイルに fputs 関数を使用すると、予期しない結果が生じる可能性があります。