xxxxxx(xxxxx)
次のようにフォーマット文字列を解析しようとしてsscanf
います:
sscanf(command, "%s(%s)", part1, part2)
sscanf
しかし、この形式をサポートしていないようで、その結果、part1
実際には文字列全体が含まれています。
誰でもこれを経験したことがある人は共有してください...
ありがとうございました
コードをプログラムに変換する:
#include <stdio.h>
int main(void)
{
char part1[32];
char part2[32];
char command[32] = "xxxxx(yyyy)";
int n;
if ((n = sscanf(command, "%s(%s)", part1, part2)) != 2)
printf("Problem! n = %d\n", n);
else
printf("Part1 = <<%s>>; Part2 = <<%s>>\n", part1, part2);
return 0;
}
実行すると、' Problem! n = 1
'が生成されます。
これは、最初の%s
変換指定子が先頭の空白をスキップしてから、次の空白文字(またはこの場合は文字列の終わり)まで「非空白」文字をスキャンするためです。
必要な結果を得るには、 (否定された)文字クラスまたはスキャンセットを使用する必要があります。
#include <stdio.h>
int main(void)
{
char part1[32];
char part2[32];
char command[32] = "xxxxx(yyyy)";
int n;
if ((n = sscanf(command, "%31[^(](%31[^)])", part1, part2)) != 2)
printf("Problem! n = %d\n", n);
else
printf("Part1 = <<%s>>; Part2 = <<%s>>\n", part1, part2);
return 0;
}
これにより、次のものが生成されます。
Part1 = <<xxxxx>>; Part2 = <<yyyy>>
形式の31に注意してください。それらはオーバーフローを防ぎます。
%31はどのように機能するのでしょうか。それはオーバーフローを防止するように機能しますか、
%s
それとも単にオーバーフローを防止しますか?
与えられたデータでは、これらの2つの行は同等であり、どちらも十分に安全です。
if ((n = sscanf(command, "%31[^(](%31[^)])", part1, part2)) != 2)
if ((n = sscanf(command, "%[^(](%[^)])", part1, part2)) != 2)
表記は%[...]
変換仕様です。です%31[...]
。
C規格は次のように述べています。
各変換仕様は、文字%で導入されます。%の後に、次のように順番に表示されます。
- オプションの割り当て抑制文字*。
- 最大フィールド幅(文字数)を指定する、ゼロより大きいオプションの10進整数。
- 受信オブジェクトのサイズを指定するオプションの長さ修飾子。
- 適用する変換のタイプを指定する変換指定文字。
31は、(オプションの)最大フィールド幅の例です。[...]
パーツはスキャンセットであり、おそらくs
変換指定子の特殊なケースと見なすことができます。変換指定子は、%s
とほぼ同等%[^ \t\n]
です。
31は文字列の長さより1つ短いです。最後のnullは、その長さではカウントされません。part1
とpart2
はそれぞれ32の配列であるためchar
、%31[^(]
または%31[^)]
変換指定子はバッファオーバーフローを防ぎます。文字の最初の文字列がの前に31文字を超えていた場合(
、リテラルの開き括弧が一致しないため、戻り値は1になります。)
同様に、2番目の文字列は31文字に制限されますが、が正しい場所にあるかどうかを簡単に判断することはできません。
「コマンド」の一部の長さが正確にわかっている場合、最も簡単なオプションは次のとおりです。
sscanf(command, "%6s(%5s)", part1, part2);
これは、「part1」が常に6文字の長さであり、「part2」が常に5文字の長さであることを前提としています(コードサンプルのように)。
代わりにこれを試してください:
#include <stdio.h>
int main(void)
{
char str1[20];
char str2[20];
sscanf("Hello(World!)", "%[^(](%[^)])", str1, str2);
printf("str1=\"%s\", str2=\"%s\"\n", str1, str2);
return 0;
}
出力 ( ideone ):
str1="Hello", str2="World!"