开发了一种替代方案

我开发了自己的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; } 

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

你的function和strtok的差异:

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

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

话虽如此,我会提出如何更好地发挥作用的建议,而不是更接近strtok实施的function。

如何改进你的function(不模仿strtok):

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

  • 让你的函数简单地返回’next’标记
  • 当你有* source或* source == delimiter时,打破你的循环
  • 返回指向包含下一个标记的源字符串的第一个字符的指针。 该指针可用于后续调用。

这段代码根本不像strtok()那样起作用。 你准备做什么,确切地说? 但就改进而言,你的代码有一个严重的错误:如果source的长度减去token的出现次数大于dest的长度你就得到了一个非常经典的Stack溢出 ,这对我来说似乎有点讽刺在这一刻。 这不会发生在您使用的main中,但在其他地方使用该function必然会引导您进入不确定性和绝望的泥潭。

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

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

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

从我看到的所有代码都忽略了任何等于令牌分隔符的输入字符,并继续复制到源的空终止。

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

strtok用NUL字符破坏输入字符串,这使它变得充满敌意。

您还需要考虑“xyz,pdq”的情况,如果’,’是分隔符,将从该字符串中删除多少令牌。

在这种情况下,您希望您的function是什么?

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

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