【问题标题】:strtok problem in calling调用中的strtok问题
【发布时间】:2010-04-05 20:42:09
【问题描述】:

我有一个像这样使用 strtok 的函数

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

我有一个电话 f1("abc,def");

问题是在第一次调用 f1 得到 abc,def 并且在第二次通话中只得到 abc

我很困惑..为什么会这样?

【问题讨论】:

  • 这是真正的代码吗?只有你在函数中有namesname 作为参数。
  • strtok 修改您传递给它的字符串。如果你不想这样,你需要保存一个副本。并且因为strtok 修改了字符串,所以使用只读字符串(strtok("abc,def");)调用它是未定义的。如果可以,请发布真实代码。

标签: c strtok


【解决方案1】:

strtok() 通过用 0 覆盖分隔符来修改其输入字符串;因此,假设您的代码如下所示:

char parm[] = "abc,def";

f1(parm);
f1(parm);

在第一次调用 f1 之后,',' 字符被一个 0 覆盖,它是一个字符串终止符,所以第二次调用只看到“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, " ,");
  }
}

【讨论】:

    【解决方案2】:

    你说:

    我有一个电话 f1("abc,def");

    该调用是非法的 - strtok 修改了它的第一个参数,并且不允许您修改字符串文字。你得到的是未定义的行为——任何事情都可能发生。你想要:

    char a[] = "abc,def";
    f1( a );
    

    【讨论】:

      【解决方案3】:

      你真的在传递字符串文字吗?

      f1("abc,def");
      

      会将指向字符串文字的指针传递给f1() 中的strtok() - 因为strtok() 修改了字符串,并且无法修改字符串文字,所以你会得到未定义的行为(尽管我会预计会发生崩溃或故障,而不是意外结果)。

      【讨论】:

        【解决方案4】:

        strtok 在它返回的每个标记之后放置一个空终止符。这意味着它破坏了原始字符串:调用它后,您的字符串将在第一个令牌之后终止,从而导致您看到的行为。

        要保持原始字符串不变,您需要在调用 strtok 之前对其进行复制。

        【讨论】:

          猜你喜欢
          • 2011-12-04
          • 1970-01-01
          • 1970-01-01
          • 2011-03-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多