
C言語入門|1文字列をまとめて読み書きする:fputsとfgets
1文字ずつから、ひとかたまりへ
これまでの記事では、ファイル入出力の基本として、
- ファイルのオープンとクローズ
- 1文字ずつ読み書きする方法
を体験してきました。
1文字単位の入出力は仕組みが分かりやすい反面、
文字数が多くなると、どうしても処理が増えてしまいます。
そこで今回は、
文字列をまとめて扱える便利な関数 を紹介します。

fputs と fgets の役割
文字列単位でファイル入出力を行う代表的な関数が、次の2つです。
| 関数名 | 役割 |
|---|---|
| fputs | 文字列をまとめてファイルに書き込む。 |
| fgets | ファイルから1行分の文字列を読み取る。 |
どちらも stdio.h に定義されており、
テキストファイルの読み書きで非常によく使われます。
文字列をまとめて書き、1行ずつ読む例
次のプログラムは、
- 複数行の文字列をまとめてファイルへ書き込み
- そのファイルを1行ずつ読み取り
- 画面に表示する
という処理を行います。
サンプルプログラム
プロジェクト名:14-7-1 ソースファイル名: sample14-7-1.c
Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE* fp;
char buf[64];
// 書き込み専用でオープン
fp = fopen("sample.txt", "w");
if (fp == NULL) {
exit(1);
}
fputs("Learning C language\nis fun and practical\nstep by step", fp);
fclose(fp);
// 読み取り専用でオープン
fp = fopen("sample.txt", "r");
if (fp == NULL) {
exit(1);
}
while (fgets(buf, 64, fp) != NULL) {
printf("%s", buf);
}
printf("\n");
fclose(fp);
return 0;
}fputs ― 文字列をまとめて書き込む
書式
int fputs(const char* dest, FILE* fp)引数と戻り値
| 項目 | 内容 |
|---|---|
| dest | 書き込む文字列 |
| fp | 書き込み先ファイルのファイルポインタ |
| 戻り値 | 正常時は0、失敗時は EOF |
fputs の動作
fputs は、
- ヌル文字で終わる文字列を受け取り
- ヌル文字の直前までを
- まとめてファイルへ書き込む
という関数です。
ポイントは、
ヌル文字そのものは書き込まれない という点です。
そのため、文字列の途中にヌル文字が含まれている場合、
そこまでしか書き込まれません。
fgets ― ファイルから1行を読み取る
書式
char* fgets(char* dest, int maxlen, FILE* fp)引数と戻り値
| 項目 | 内容 |
|---|---|
| dest | 読み取った文字列を格納する配列 |
| maxlen | 読み取る最大バイト数 |
| fp | 読み取り元ファイルのファイルポインタ |
| 戻り値 | dest、終端または失敗時は NULL |
fgets の動作
fgets は、次のいずれかまでを読み取ります。
- 改行文字が現れたところまで
- ファイルの終端まで
- 指定した最大サイズの手前まで
読み取った結果は、必ず
- 改行文字(存在すれば)
- ヌル文字
を含む形で配列に格納されます。
改行文字とヌル文字の扱い
fgets を使うときに特に重要なのが、
改行文字とヌル文字の扱い です。
| 状況 | 配列に格納される内容 |
|---|---|
| 改行がある | 文字列 + 改行文字 + ヌル文字 |
| 改行がない | 文字列 + ヌル文字 |
つまり、
改行文字も文字列の一部として扱われる点に注意が必要です。
そのため、表示や文字列処理を行う際に、
改行を除去したい場合は追加処理が必要になることもあります。
第2引数 maxlen の重要性
fgets の第2引数は、
読み取ってよい最大バイト数 を指定します。
これは、安全のために非常に重要です。
もしファイルに、
- 改行がまったく存在しない。
- 非常に長い1行が続く。
といったデータがあった場合、
制限なしで読み取ると、
配列のサイズを超えて書き込んでしまう危険があります。
fgets は、
- 最大 maxlen - 1 文字まで読み取り。
- 最後に必ずヌル文字を付加する。
という動作をすることで、
バッファオーバーフローを防いでいます。
fputs と fgets の特徴まとめ
メリット
| 項目 | 内容 |
|---|---|
| 処理が簡潔 | ループ回数が減る。 |
| 可読性が高い | コードがわかりやすい。 |
| 安全性 | fgets は最大サイズを指定できる。 |
注意点
| 項目 | 内容 |
|---|---|
| 改行文字 | fgets は改行も読み取る。 |
| ヌル文字 | fputs はヌル文字までしか書かない。 |
| サイズ管理 | バッファサイズを意識する必要がある。 |
ここまでのまとめ
この節で押さえておきたいポイントは次のとおりです。
- fputs は文字列をまとめて書き込む。
- fgets は1行単位で安全に読み取れる。
- 改行文字とヌル文字の扱いを理解する。
- fgets の第2引数は必ず指定する。
1文字単位の入出力を理解した上で、
文字列単位の関数を使えるようになると、
C言語のファイル操作が一気に楽になります。
この内容を理解できれば、
テキストファイルの読み書きはもう怖くありません 👍
