_scanf(" %[^\n]",line);
_
私の友人は、上記のステートメントのようにfgets()
を使用するよりも、入力として行を読み取るためにscanf()
を使用することをお勧めします。彼は正当化されますか?
char * fgets ( char * str, int num, FILE * stream );
は、 buffer overflow の問題を回避するため、安全に使用できます。_num-1
_個のcharのみをスキャンします。
ストリームから文字を読み取り、(num-1)文字が読み取られるか、改行またはファイルの終わりに達するまで(どちらか早い方)、C文字列としてstrに格納します。
ここで、2番目の引数num
は、strにコピーされる最大文字数(終端のヌル文字を含む)です。
たとえば、コードの文字列配列の容量が、以下のように_5
_文字だけであるとします。
_ char str[5];
fgets (str, 5, fp); //5 =you have provision to avoid buffer overrun
_
上記のコードを使用して、fp
からの入力が_4
_ charsより長い場合、fgets()
は最初に_4
_ charsを読み取り、その後_\0
_(、およびその他の余分な入力文字を破棄し、_str[]
_)に5文字を格納します。
scanf(" %[^\n]",str);
は_\n
_が見つからなくなるまで読み取り、入力文字列が長い場合は_4
_ chars scanf()
は buffer overflow の原因になります(scanf
は_4
_の最大インデックス_str[]
_を超えてメモリにアクセスしようとします)。
C FAQには、scanf
の問題に関する詳細な説明があります。
より一般的には、
scanf
は比較的構造化され、フォーマットされた入力用に設計されています(その名前は実際には「スキャンフォーマット済み」から派生しています)。注意を払うと、成功したか失敗したかがわかりますが、失敗したおおよその場所のみがわかり、方法や理由はわかりません。エラー回復を行う機会はほとんどありません。
詳細については here を参照してください。
簡単に言えば、はい、fgets
がより良い選択です。
私はあなたのscanf
フォーマット指定子を見ましたが、私は不可解でした。それが何をするかを正確に理解するには、man
ページを読むのに時間がかかります。
また、scanf
コードはバッファオーバーランの影響を受けやすくなります。
シンプルに保つと、メンテナンスコストが削減され、バグを見つけにくくなります。
fgets
は、このscanf
よりも優れています。 OPで指定されているscanf
には次の問題がある可能性があります
1)@Grijeshが示唆するバッファオーバーフロー
2)入力ストリームに改行が残っているため、この後の次のscanf
は機能しません。(空白が欠落している場合)
はい、fgetsは標準入力から行を読み取るためのより安全で安全な方法です。
さらに、コードが読みやすくなります。あなたから与えられたscanfステートメントを見てください。
それを見た二人目は完全に混乱します。ただし、fgetsの方が読みやすくなり、理解しやすくなります。