KernighanとPikeは、著書『プログラミング作法』(読む価値があります)でこの問題について説明し、関数ファミリーにsnprintf()
渡すための正しいバッファーサイズで文字列を作成することで問題を解決していscanf()
ます。事実上:
int scanner(const char *data, char *buffer, size_t buflen)
{
char format[32];
if (buflen == 0)
return 0;
snprintf(format, sizeof(format), "%%%ds", (int)(buflen-1));
return sscanf(data, format, buffer);
}
これでも、入力は「バッファ」として提供されるサイズに制限されることに注意してください。より多くのスペースが必要な場合は、メモリ割り当てを行うか、メモリ割り当てを行う非標準のライブラリ関数を使用する必要があります。
注のPOSIX 2008(2013)バージョンというscanf()
機能の家族はフォーマット修飾子をサポートm
文字列入力用(割り当て割り当て文字を() 、%s
、)。%c
引数%[
を取る代わりに、char *
引数を取り、char **
読み取る値に必要なスペースを割り当てます。
char *buffer = 0;
if (sscanf(data, "%ms", &buffer) == 1)
{
printf("String is: <<%s>>\n", buffer);
free(buffer);
}
sscanf()
関数がすべての変換仕様を満たさない場合、関数が%ms
戻る前に、同様の変換に割り当てられたすべてのメモリが解放されます。
buflen-1
—ありがとう。次に、符号なしのアンダーフロー(かなり大きな数にラップする)、つまりif
テストについて心配する必要があります。サイズとして0を渡すのに不注意な人がいる場合はassert()
、それをに置き換えたり、開発中に発生するassert()
前にバックアップしたりすることを強く望んでif
います。%0s
意味についてドキュメントを注意深く確認していませんsscanf()
—テストはとしてより良いかもしれませんif (buflen < 2)
。