C言語のfgetsを使う方法
目次
C言語のfgetsの使い方
C言語のfgets関数はファイルポインタから1行読み込むときに使われます。
この関数はC言語では比較的によく使われる利用頻度の高い関数です。
この記事ではfgets関数の使い方を詳しく解説します。
この記事を読めばfgets関数の使用方法がわかります。
不明なブロック名です。
fgets関数の構造
fgets関数の構造は↓のようになっています。
#include <stdio.h> /** * streamからsizeを上限として1行をsに読み込む。 * EOFに達したまたはエラーの場合はNULLを返し、それ以外はsへのポインタを返す。 */ char *fgets(char *s, int size, FILE *stream);
fgets関数は3つの引数を取りchar型のポインタの返り値を返します。
引数はs
, size
, stream
の3つです。
s
は読み込んだバッファを保存する先のポインタです。
これは通常は文字配列のアドレスが渡されます。
size
は読み込みの最大サイズです。
通常はs
のサイズを渡します。
stream
は読み込み元のファイルポインタです。
fopen()
で開いたファイルポインタやstdin
などを指定できます。
返り値は正常の場合はs
のアドレスです。
EOFに達した場合やエラーになった場合はNULLを返します。
EOFとは「End Of File」の略でファイル終端を表す概念です。
fgets関数を使ってみる
実際にfgets関数を使ってみます。
char buf[100]; fgets(buf, sizeof buf, stdin); printf("buf[%s]\n", buf); // 123 // buf[123 // ]
↑のコードではfgetsの第1引数には文字配列buf
を指定しています。
そして第2引数にはbuf
のサイズ、つまりsizeof
で求めた文字配列buf
のバイト数を指定します。
第3引数には標準入力のファイルポインタであるstdin
を指定しています。
↑のプログラムを実行すると画面が入力待ちになります。
123
と入力してエンターキーを押すとその入力がbuf
に保存されます。
printf("buf[%s]\n", buf);
でbuf
を出力する
buf[123 ]
と出力されます。
注目したいのはエンターキーで入力した改行もbuf
に保存されている点です。
このようにfgets関数は改行も一緒にバッファに保存します。
fgets関数の返り値をチェックしてみる
fgets関数の返り値をチェックしてみます。
char buf[100]; char *p = fgets(buf, sizeof buf, stdin); if (p == buf) { printf("同じ\n"); } // 同じ
↑のコードを実行すると「同じ」と表示されます。
fgets関数が正常時に返すポインタのアドレス値とbuf
のアドレス値が同じであることがわかります。
もちろんこれはfgets関数がNULLを返した場合は違う値になるので注意が必要です。
fgets関数で複数行を読み込む
fgets関数はループ文と一緒によく使われます。
たとえばwhile文と組み合わせると↓のようになります。
char buf[100]; while (fgets(buf, sizeof buf, stdin) != NULL) { printf("buf[%s]\n", buf); } // Ctrl + D(WindowsはCtrl + Z)で終了
↑のコードを実行すると入力待ちになります。
文字列をキーボードで入力してエンターキーを押すと再び入力待ちになります。
Ctrl + D(Windowsの場合はCtrl + Z)を押すとEOFが入力されfgets関数からNULLが返りループが終了します。
↑の場合はstdin
(標準入力)から読み込んでいますがこれはもちろんfopen()
で開いたファイルポインタも指定できます。
ファイル内容を1行ずつ処理したい場合などはこのようなコードで処理することができます。
ファイルを開いて1行ずつ読み込む
ファイルを開いて1行ずつ読み込みたい場合は↓のようなコードを書きます。
// ファイルを開いて1行ずつ読み込む FILE *fin = fopen("main.c", "r"); if (fin == NULL) { perror("fopen"); return 1; } char buf[100]; while (fgets(buf, sizeof buf, fin) != NULL) { printf("%s", buf); } fclose(fin);
このコードをmain.c
などで保存します。
でmain
関数の中に↑のコードを置いておきます。
そして実行するとmain.c
のファイル内容が読み込まれます。
ループ中のprintf()
では改行は出力していません。
これはfgets()
で読み込んだbuf
に改行が含まれているからです。
改行を連続して出力することになるのでprintf()
では改行は出力しません。
fgets関数のエラーの検知
fgets関数はEOFに達した場合とエラーになった場合にどちらもNULLを返します。
エラーを検知したい時はどうすればいいのでしょうか?
これはferror()
を使います。
↓のコードはわざとエラーを発生させるコードです。
// このコードはわざとエラーが発生するようになっている FILE *fin = fopen("main.c", "a"); // "a"になっている if (fin == NULL) { perror("fopen"); return 1; } char buf[100]; // モード"a"のファイルから読み込む(エラー) char *result = fgets(buf, sizeof buf, fin); printf("result[%s]\n", result); if (ferror(fin) != 0) { perror("fgets"); } fclose(fin); // result[(null)] // fgets: Bad file descriptor
↑のエラーですがまずfopen()
でファイルを開いています。
その時にオープンモードを「a
」にしています。
a
は追記モードです。ですので読み込みには対応していません。
この状態のファイルポインタをfgets()
で読み込もうとするとエラーになります。
↑のコードではfgets()
の返り値はNULLになっています。
これはエラーが発生していることを示しています。
ferror()
はファイルポインタを調べてエラーが発生していたら0
以外の値を返します。
つまり条件式ferror(fin) != 0
が真になるというのはファイルポインタがエラーを抱えてる状態になります。
エラーが発生していたらperror("fgets")
でエラー表示します。
perror()
はerrno
を文字列にしてエラー表示してくれる関数です。
perror()
の出力は「fgets: Bad file descriptor
」になります。
「ファイルディスクリプタが変」というエラーですね。追記モードで開いているファイルなのに読み込もうとしてるからこういうエラーになったわけですね。
おわりに
今回はC言語のfgets関数の使い方を解説しました。
fgets関数はよく使いますので使い方は暗記しておいた方がいいでしょう。
なにか参考になれば幸いです。
(^ _ ^) | 一行取得! |
(・ v ・) | 読み込んでやる! |