【问题标题】:developed a strtok alternative开发了一个 strtok 替代方案
【发布时间】:2009-03-23 15:48:03
【问题描述】:

我开发了自己的 strtok 版本。只是为了练习使用指针。

任何人都可以看到这方面的任何限制,或者无论如何我可以改进。

void stvstrtok(const char *source, char *dest, const char token) 
{
    /* Search for the token. */
    int i = 0;
    while(*source)
    {
        *dest++ = *source++;
        if(*source == token)
        {
            source++;
        }
    }
    *dest++ = '\0';
    }

int main(void)
{
    char *long_name = "dog,sat ,on ,the,rug,in ,front,of,the,fire";
    char buffer[sizeof(long_name)/sizeof(*long_name)];

    stvstrtok(long_name, buffer, ',');

    printf("buffer: %s\n", buffer);

   getchar();

   return 0;
}

【问题讨论】:

  • strtok 应该返回下一个标记,但是这段代码只是删除了分隔符。
  • 发送一些缺少 '\0' 的有缺陷的字符串,看看会发生什么,这段代码如何处理 NULL 或随机字符串?

标签: c pointers strtok


【解决方案1】:

附注:“token”一词通常用于描述返回的字符串部分。 Delimiter 用于描述分隔标记的事物。因此,为了使您的代码更清晰,您应该将 token 重命名为 delimiter 并将 dest 重命名为 token_dest。

你的函数和 strtok 的区别:

你的函数和 strtok 有几个不同。

  • 您的函数所做的只是删除标记分隔符
  • 您只需调用一次函数即可处理字符串的所有部分。使用 strtok 您可以为字符串的每个部分多次调用它(随后将 NULL 作为第一个参数)。
  • strtok 还会破坏源字符串,而您的代码使用自己的缓冲区(我认为最好像您一样使用自己的缓冲区)。
  • strtok 存储每次调用后第一个参数为 NULL 的下一个标记的位置。该位置随后用于后续调用。虽然这不是线程安全的,但您的函数将是线程安全的。
  • strtok 可以使用多个不同的分隔符,而您的代码只使用一个。

话虽如此,我将就如何制作更好的函数给出建议,而不是更接近 strtok 实现的函数。

如何改进你的功能(不是模仿 strtok):

我认为进行以下更改会更好:

  • 让您的函数简单地返回“下一个”标记
  • 当您有 *source 或 *source == 分隔符时跳出循环
  • 返回指向包含下一个标记的源字符串的第一个字符的指针。该指针可用于后续调用。

【讨论】:

    【解决方案2】:

    这段代码根本不像strtok()那样运行。你到底想做什么?但就改进而言,您的代码有一个严重的错误:如果source 的长度减去token 的出现次数大于dest 的长度,那么您就得到了一个非常经典的堆栈溢出,这对我来说似乎有点讽刺。在你使用过的main 中不会发生这种情况,但在其他地方使用该功能势必会导致你走入不确定的道路和绝望的泥潭。

    【讨论】:

      【解决方案3】:

      strtok 允许您遍历所有标记。它通过假设源字符串是可写的并在标记中断处将空值插入其中来实现这一点。目标缓冲区是指向源缓冲区中字符偏移量的指针。您可以使用这一事实来了解何时到达终点 + 还可以在通话之间保持“状态”。

      Strtok 不是一个好用的函数,因为它会破坏源字符串。它也是不可重入的。

      【讨论】:

      • 关于重入:strtok_r()
      【解决方案4】:

      strtok() 会保存一些状态,所以你可以多次调用它来获取多个令牌。此外,strtok() 将“拆分”源字符串,以便您获得多个目标字符串,每个字符串都是一个标记。

      据我所知,您的所有代码所做的都是忽略任何等于标记分隔符的输入字符,并继续复制到源的空终止符。

      edit:另外,考虑有两个排序标记分隔符:第一个将被您的函数忽略,第二个将被写入目标,而 strtok() 会将 2 个或更多分隔符的序列定义为单个分隔符(手册页:http://man.cx/?page=strtok

      【讨论】:

        【解决方案5】:

        strtok 用 NUL 字符破坏输入字符串,这使它有点敌意。

        您还需要考虑“xyz,,pdq”的情况,如果 ',' 是分隔符,strtok 将从该字符串中拉出多少个标记。

        在这种情况下你希望你的函数做什么?

        【讨论】:

          【解决方案6】:

          另外,strtok(...) 支持多个分隔符。查看 strspn(...) 和 strcspn(...) 的定义,因为它们可用于重新实现 strtok(...)。

          【讨论】:

            【解决方案7】:

            顺便说一下,long_name 是指向 char 的指针,而 sizeof(long_name) 是 sizeof(char*)。 不是 long_name 所指向的大小。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2011-12-15
              • 2012-01-27
              • 2012-05-20
              • 2011-05-30
              • 1970-01-01
              • 1970-01-01
              • 2011-11-27
              • 1970-01-01
              相关资源
              最近更新 更多