2

xxxxxx(xxxxx)次のようにフォーマット文字列を解析しようとしてsscanfいます:

sscanf(command, "%s(%s)", part1, part2)

sscanfしかし、この形式をサポートしていないようで、その結果、part1実際には文字列全体が含まれています。

誰でもこれを経験したことがある人は共有してください...

ありがとうございました

4

3 に答える 3

7

コードをプログラムに変換する:

#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は、その長さではカウントされません。part1part2はそれぞれ32の配列であるためchar%31[^(]または%31[^)]変換指定子はバッファオーバーフローを防ぎます。文字の最初の文字列がの前に31文字を超えていた場合(、リテラルの開き括弧が一致しないため、戻り値は1になります。)同様に、2番目の文字列は31文字に制限されますが、が正しい場所にあるかどうかを簡単に判断することはできません。

于 2012-09-13T04:05:04.897 に答える
2

「コマンド」の一部の長さが正確にわかっている場合、最も簡単なオプションは次のとおりです。

sscanf(command, "%6s(%5s)", part1, part2);

これは、「part1」が常に6文字の長さであり、「part2」が常に5文字の長さであることを前提としています(コードサンプルのように)。

于 2012-09-13T04:07:07.087 に答える
1

代わりにこれを試してください:

#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!"
于 2012-09-13T04:10:06.657 に答える