4

strtokを使用して文字列madddyを分割する次のスニペットについて考えてみます。

char* str = (char*) malloc(sizeof("Madddy"));
strcpy(str,"Madddy");

char* tmp = strtok(str,"d");
std::cout<<tmp;

do
{
    std::cout<<tmp;
    tmp=strtok(NULL, "dddy");
}while(tmp!=NULL);

正常に動作し、出力はMaです。しかし、strtokを次のように変更することにより、

tmp=strtok(NULL, "ay");

出力はMaddになります。では、strtokはどのように正確に機能しますか?strtokが区切り文字列にあるすべての文字を区切り文字として受け取ることを期待していたので、この質問があります。しかし、それがそのように行われている場合もありますが、予期しない結果をもたらす場合もあります。誰かが私がこれを理解するのを手伝ってもらえますか?

4

6 に答える 6

10

「strtokを理解しようとしています」頑張ってください!

とにかく、私たちは2011年にいます。適切にトークン化:

std::string str("abc:def");
char split_char = ':';
std::istringstream split(str);
std::vector<std::string> token;

for (std::string each; std::getline(split, each, split_char); token.push_back(each));

:D

于 2011-01-14T02:34:05.940 に答える
3

フレッドフリントストーンはおそらく使用しstrtok()ました。これはマルチスレッド環境よりも前のものであり、ソース文字列を打ち負かします(変更します)。

最初のパラメーターに対してwithを呼び出すとNULL、最後の文字列の解析が続行されます。この機能は便利でしたが、当時でも少し変わっていました。

于 2011-01-14T02:37:08.000 に答える
2

実際、コードが間違っているので、予期しない結果が生じるのも不思議ではありません。

char* str = (char*) malloc(sizeof("Madddy"));

する必要があります

char* str = (char*) malloc(strlen("Madddy") + 1);
于 2011-01-14T02:40:27.433 に答える
1

区切り文字「d」で初めて(ループ外で)strtokを呼び出したことを忘れているようです。

strtokは正常に動作しています。ここに参照があるはずです。

2番目の例(strtok("ay"))の場合:

まず、strtok(str、 "d")を呼び出します。最初の「d」を探し、文字列を区切ります。具体的には、tmp = "Ma"、str = "ddy"(最初の "d"を削除)を設定します。

次に、strtok(str、 "ay")を呼び出します。strで「a」を検索しますが、文字列は「ddy」のみであるため、一致は発生しません。次に、「y」を探します。したがって、str="dd"およびtmp=""です。

あなたが見たようにそれは「マッド」を印刷します。

于 2011-01-14T03:02:47.017 に答える
0

セキュリティ問題/バッドプラクティス関数を引き起こす関数とc標準ライブラリについての別の質問から着想を得た質問をしました。

そこから私に与えられた答えを引用するには:

この関数の一般的な落とし穴はstrtok() 、解析された文字列が変更されないままであると想定することですが、実際には区切り文字を。に置き換え'\0'ます。

また、strtok()文字列全体がトークン化されるまで、後続の呼び出しを行うことによって使用されます。一部のライブラリ実装は、の内部ステータスをグローバル変数に格納 します。これは、同時に複数のスレッドから呼び出されたstrtok()場合に、厄介な驚きを引き起こす可能性があります。strtok()

質問にC++のタグを付けたので、他のものを使用してください。Cを使用する場合は、安全に機能する独自のトークナイザーを実装することをお勧めします。

于 2011-01-14T02:48:08.950 に答える
0

タグをC++ではなくCに変更したので、何が起こっているかを確認できるように、printfを使用するように関数を書き直しました。ホアンは正しいです。正しい出力が表示されていますが、すべてを同じ行に印刷していると思うので、出力に混乱しました。彼が正しく起こっていることを説明しているので、ホアンの答えを見てください。また、他の人が指摘しているように、strtokは入力文字列を破棄するので、注意する必要があります-そしてそれはスレッドセーフではありません。しかし、迅速なダーティトークナイザーが必要な場合は、機能します。また、Andersが正しく指摘したように、sizeofではなく、strlenを正しく使用するようにコードを変更しました。

よりCに似たものに変更されたコードは次のとおりです。

char* str = (char*) malloc(strlen("Madddy") + 1);
strcpy(str,"Madddy");

char* tmp = strtok(str,"d");
printf ("first token: %s\n", tmp);

do
{
    tmp=strtok(NULL, "ay");
    if (tmp != NULL ) {
       printf ("next token: %s\n", tmp);
    }
} while(tmp != NULL);
于 2011-01-14T19:52:19.570 に答える