1

このようなstrtokを使った機能があります

void f1(char *name)
{
...
char *tmp;
tmp = strtok(names, " ,");
while(tmp)
{
...
tmp = strtok(NULL, " ,");
}
...
}

そして、私はf1( "abc、def");という呼び出しを持っています。

問題は、最初の呼び出しでf1がabc、defを取得し、2番目の呼び出しでabcだけを取得することです。

私は混乱しています..なぜこれがそうなのですか?

4

4 に答える 4

4

strtok()区切り文字を0で上書きすることにより、入力文字列を変更します。したがって、コードが次のようになっていると仮定します。

char parm[] = "abc,def";

f1(parm);
f1(parm);

f1を最初に呼び出した後、「、」文字は文字列ターミネータである0で上書きされるため、2番目の呼び出しでは「abc」のみが文字列として認識されます。

strtok()入力を変更するため、引数として文字列リテラルを渡したくないことに注意してください。文字列リテラルの内容を変更しようとすると、未定義の動作が発生します。

安全な方法は、f1内にローカル文字列を作成し、名前の内容をコピーしてから、そのローカル文字列をに渡すことstrtok()です。以下はC99で動作するはずです:

void f1(char *name)
{
  size_t len = strlen(name);
  char localstr[len+1];
  char *tmp;
  strcpy(localstr, name);

  tmp = strtok(localstr, " ,");
  while(tmp)
  {
    ...
    tmp = strtok(NULL, " ,");
  }
}
于 2010-04-05T20:57:50.813 に答える
2

あなたは言う:

そして、私はf1( "abc、def");という呼び出しを持っています。

その呼び出しは不正です-strtokは最初のパラメーターを変更し、文字列リテラルを変更することは許可されていません。あなたが得るのは未定義の振る舞いです-何かが起こる可能性があります。あなたが欲しい:

char a[] = "abc,def";
f1( a );
于 2010-04-05T20:56:16.940 に答える
1

あなたは本当に文字列リテラルを渡していますか?

f1("abc,def");

文字列を変更するため、文字列リテラルへのポインタをinに渡します。文字列リテラルstrtok()は変更できないため、未定義の動作が発生します(ただし、予期しない結果ではなく、クラッシュまたは障害が発生することが予想されます)。f1()strtok()

于 2010-04-05T20:56:43.510 に答える
-1

strtok返す各トークンの後にnullターミネータを置きます。これは、元の文字列を破棄することを意味します。呼び出した後、文字列は最初のトークンの後で終了し、表示される動作になります。

元の文字列を変更しないようにするには、を呼び出す前にそのコピーを作成する必要がありますstrtok

于 2010-04-05T20:55:11.693 に答える