を考えると、次の行:文字列の形式%80 [^、]はCの意味ですか?
char szInline[80];
char szDescription[80] = { NULL };
float fCost = 0;
sscanf (szInline, "%80[^,], %f", szDescription, &fCost);
% 80 [^は、]何をしますか?
を考えると、次の行:文字列の形式%80 [^、]はCの意味ですか?
char szInline[80];
char szDescription[80] = { NULL };
float fCost = 0;
sscanf (szInline, "%80[^,], %f", szDescription, &fCost);
% 80 [^は、]何をしますか?
最大80文字を次の,
のカンマまで読みます。
ところで、szDescription
バッファここで1
「小さすぎる1」のバグをうまくキャッチ! – dasblinkenlight
@dasblinkenlight:良いバグ候補ですが、入力文字列の最大長が79なのでこの特定のケースでは何の結果もありません。 – chqrlie
@AnT:定義: 'char szInline [80];' 'szInline'が適切な文字列でない場合(ヌルバイトを含まない)場合、コードは未定義のビヘイビアを呼び出します。フラグメントは 'szInline'の初期化を省略していると仮定していますが、省略記号' ... 'はより明白になります。 – chqrlie
によって小さすぎるはsscanf(szInline, "%80[^,], %f", szDescription, &fCost)
ためのステップである:
sscanf
はszDescription
に,
異なる1
と80
文字間解析します成功した場合は、,
文字に一致すると見なされます。'\n'
を含む)を無視します。fCost
タイプのfloat
に変換しようとすると、EOF
は早期の失敗のケースです。そこに潜在的な問題があります。
szDescription
は80文字プラス'\0'
ターミネータ用短すぎるが、それならば幸いにも、入力配列szInline
も80の長さを有し適切な文字列が含まれています。最大で79
文字はsscanf
と一致するため、オーバーフローは発生しません。この特定の場合、サイズ指定子は実際には必要ありません。,
の後のスペースは冗長です。 %f
は常に先頭の空白を無視します。sscanf()
は、この入力にEOF
を返すことに注意してください:入力文字列の先頭から解析する,
異なる何文字が含まれていないとして,1
。この特殊なケースは、高度なCプログラマでさえ見過ごされがちです。
あなたが,
前に、おそらく空の文字列を受け入れるようにしたい場合は、あなたが直接sscanf()
を使用することはできませんが、これを使用することができます:
/* compute the length of the initial sequence upto `,` if any */
size_t len = strcspn(szInline, ",");
/* len < 80 because sizeof(szInline) == 80 */
/* copying the initial string */
memcpy(szDescription, szInline, len);
szDescription[len] = '\0';
if (sscanf(szInline + len, ",%f", &fCost) != 1) {
/* conversion error: no `,` or no number past it */
...
}
sscanf()
は、多くの癖を持っている、何のために適切に使用することが難しいことで知らあります最も単純な解析作業です。めったに使用されない標準機能strspn()
とstrcspn()
は有用な代替手段です。
scanfをオプションで80文字までマッチさせることができますか?1も成功するでしょうか? –
'sscanf()'では直接ではありません。私の更新された答えを見てください。 – chqrlie
btw '{NULL}'は '{0}'または '{'\ 0'}'でなければなりません。 'NULL'は値0を持つポインタです。それを文字に代入すると、"整数変換への互換性のないポインタ "*警告が与えられます。 – user3386109
@ user3386109:残念ながら、警告は表示されません。 'NULL'は、実装定義のヌルポインタ定数に展開され、通常は' 0'です。(もちろん、NULLポインタ定数*が必ずしもポインタ型の式であるとは限りません) –
@ user3386109: 'NULL(NULL)'を '(void *)0'として定義しても、 C標準ライブラリの実装では非常に一般的な方法ですが、 'NULL'はポインタであることが保証されていません。このコードを有効にする整数値「0」にすることができます。しかし、あなたのポイントはまだ立っています。 「NULL」はそこにビジネスがありません。 'NULL'はポインタコンテキストにのみ予約されるべきです。 – AnT