これに関する1つの問題:
result = fscanf(fp, "%[^\n]s", ap->name);
s
フォーマット指定子の最後に余分なものがあるということです。%[^\n]
フォーマット指定子全体は、「改行ではない文字で構成される文字列を読み取る」というだけのはずです。エクストラs
はフォーマット指定子の一部ではないため、リテラルとして解釈されます。「入力から次の文字を読み取ります。「s」の場合は続行し、それ以外の場合は失敗します。」
ただし、余分なs
ものは実際にはあなたを傷つけません。入力の次の文字である改行が正確にわかります。一致せず、入力処理はそこで停止しますが、書式指定子の最後なので問題ありません。ただし、同じフォーマット文字列でこの後に他のフォーマット指定子がある場合、これは問題を引き起こします。
本当の問題は、改行を消費していないことです。改行までのすべての文字を読み取っているだけで、改行自体は読み取っていません。これを修正するには、次のようにする必要があります。
result = fscanf(fp, "%[^\n]%*c", ap->name);
%*c
指定子は、文字 ( ) を読み取るように指示していc
ますが、それを変数に代入しないでください ( *
)。を省略した場合は、文字 (a) へのポインターを含む別のパラメーターを*
渡す必要があり、そこで読み取った結果の文字を格納します。fscanf()
char*
を使用することもでき%[^\n]\n
ますが、改行に続く空白も読み取られます。これは、必要なものではない可能性があります。がfscanf
書式指定子 (スペース、改行、またはタブ) に空白を見つけると、できるだけ多くの空白を消費します (つまり、正規表現に一致する最長の文字列を消費すると考えることができます[ \t\n]*
)。
最後に、バッファ オーバーランを回避するために、最大長も指定する必要があります。%
これを行うには、と の間にバッファー長を配置し[
ます。たとえば、ap->name
が 256 文字のバッファの場合、次のようにする必要があります。
result = fscanf(fp, "%255[^\n]%*c", ap->name);
これは、静的に割り当てられた配列に最適です。残念ながら、配列が実行時に動的にサイズ設定されている場合、バッファ サイズを に渡す簡単な方法はありませんfscanf
。sprintf
たとえば、次のようにフォーマット文字列を作成する必要があります。
char format[256];
snprintf(format, sizeof(format), "%%%d[^\n]%%*c", buffer_size - 1);
result = fscanf(fp, format, ap->name);