web-dev-qa-db-ja.com

fgets()は常にcharバッファーを\ 0で終了しますか?

EOFにすでに到達している場合でも、fgets()は常にcharバッファーを\ 0で終了しますか?そうなっているように見えます(ANSI K&Rブックに示されている実装では確かにそうです)が、私は確かにお願いしたいと思いました。

この質問は、gets()などの他の同様の関数にも当てはまると思います。

編集:「通常の」状況で\ 0が追加されることはわかっていますが、私の質問はEOFまたはエラー状態)を対象としています。例:

FILE *fp;
char b[128];
/* ... */
if (feof(fp)) {
    /* is \0 appended after EACH of these calls? */
    fgets(b, 128, fp);
    fgets(b, 128, fp);
    fgets(b, 128, fp);
}
17
Ree

getsは絶対に使用しないでください!!

 7.19.7.2fgets関数
概要
 1 #include <stdio.h> 
 char * fgets(char * limit s、int n、
ファイル*ストリームの制限); 
説明
 2 fgets関数は、ストリームが指すストリームからnで指定された文字数
より多くても1つ少ない文字を読み取ります。 sが指す配列
。改行文字
(保持されます)の後、またはファイルの終わりの後、追加の文字は読み取られません。配列に最後に読み込まれた文字の直後にヌル文字が書き込まれます
。
戻り値
 3成功した場合、fgets関数はsを返します。ファイルの終わりが検出され
、文字が配列に読み込まれていない場合、配列
の内容は変更されず、nullポインタが返されます。操作中に読み取りエラーが発生した場合
、配列の内容は不確定であり、null 
ポインタが返されます。

したがって、yesfgets()がNULLを返さない場合、宛先配列は常にnull文字を持ちます。

fgets()がNULLを返す場合、宛先配列が変更されている可能性があり、ヌル文字が含まれていない可能性があります。 fgets()からNULLを取得した後は、配列に依存しないでください。


編集の例を追加

 $ cat fgets_error.c 
#include <stdio.h> 
 
 void print_buf(char * buf、size_t len){
 int k ; 
 printf( "%02X"、buf [0]); 
 for(k = 1; k <len; k ++)printf( "%02X"、buf [k]); 
} 
 
 int main(void){
 char buf [3] = {1、1、1}; 
 char * r; 
 
 printf( "Enter CTRL + D:"); 
 fflush(stdout); 
 r = fgets(buf、sizeof buf、stdin); 
 printf( "\ nfgetsが%pを返し、buf has ["、(void *)r); 
 print_buf(buf、sizeof buf); 
 printf( "]\n"); 
 
 return 0; 
} 
 $ ./a.out
Enter CTRL + D:
 fgetsが返されました(nil) 、bufには[01 01 01] 
 $ 
があります

見る? bufにNULはありません:)

7
pmg

fgetsは常に読み取りバッファに '\ 0'を追加します。このため、ストリームから最大size - 1文字を読み取ります(sizeは2番目のパラメータです)。

getsを使用しないでください。指定したバッファがオーバーフローしないことを保証できないため、技術的には常に読み取り文字列を終了しますが、実際には役に立ちません。

11
CB Bailey

man fgets:

fgets()は、ストリームから最大で1つ小さいサイズの文字を読み込み、sが指すバッファーにそれらを格納します。 EOFまたは改行の後に読み取りが停止します。改行が読み取られると、バッファに格納されます。'\ 0'は、の最後の文字の後に格納されます。バッファ。

4
eyalm

バイナリモード「rb」でファイルを開いた場合、およびfgetsを使用してテキストを1行ずつ読み取りたい場合は、次のコードを使用して、誤ってテキストに '\が含まれている場合に、ソフトウェアがテキストを失うのを防ぐことができます。 0 'バイト。しかし、最後に言及した他のように、ストリームに「\ 0」が含まれている場合、通常はfgetsを使用しないでください。


size_t filepos=ftell(stream);
fgets(buffer, buffersize, stream);
len=strlen(buffer);
/* now check for > len+1 since no problem if the 
   last byte is 0 */
if(ftell(stream)-filepos > len+1) 
{
    if(!len) filepos++;
    if(!fseek(stream, filepos, SEEK_SET) && len)
    {
        fread(buffer, 1, len, stream);
        buffer[len]='\0';
    }
}
2
user4907386

はい、そうです。から CPlusPlus.com

ストリームから文字を読み取り、(num-1)文字が読み取られるか、改行またはファイルの終わりに到達するまで、C文字列としてstrに格納します。

改行文字はfgetsの読み取りを停止しますが、有効な文字と見なされるため、strにコピーされる文字列に含まれます。

C文字列の終わりを示すために、読み取られた文字の後にnull文字がstrに自動的に追加されます。

1
Ólafur Waage