看到网上好多错误的strtok实现,也不能说错,准确的说是没有完全的实现strtok,现自己写了下,目前还没有找到bug,如果有不对的欢迎指出。
大多数网上的strtok实现的代码跑不过a[]={“abc....123,,,,”},c[]={“.,”},就算跑过了,都是将a[]里的“.,”全部给置‘’了,更支持不了此等循环的调用例如:
char *ret = mystrtok(a, c);
printf("%s %s ", a, ret);
printf("%p %p ", a, ret);
while(ret != NULL)
{
ret = mystrtok(NULL, c);
printf("%s %s ", a, ret);
printf("%p %p ", a, ret);
}
以下是代码实现
#include <stdio.h>
#include <string.h>
#include <assert.h>
char *mystrtok(char *str, const char *delim)
{
assert(delim != NULL);
static char *str_next = NULL;
//用于记录置“”的后一个地址,准确的说是后一个字节地址,也就是下个字符的地址。一定要用static以免下次调用时被释放掉
//此循环的作用,是将str_next记录了置'\0'后一个字符的地址,进行了移位,,,为什么要移位呢,,因为其实strtok其实只将str字符串中有delim字符串中的字符进行了一次置'\0',而不是全部置'\0',例:字符串a[]={“ha,,,,,hihi....ser”},调用三次后,其实此时字符串a应该是“ha'\0',,,,hihi'\0'...ser”的,将数组a全部打印出来a2等于空,a11也等于空,其它字符是不变的,而不是将字符串置为“ha'\0''\0''\0''\0''\0'hihi'\0''\0''\0''\0'ser”,大家可以去打印来看看,所以我们需要将指针str_next指向“下一个字符串”,,例如上面举的a[]的例子,第二次调用strtok时str_next应该指向hihi的h地址
while(str_next != NULL && *str_next != '\0')
{
int str_num = 0;
char *delim_k = (char *)delim;
while(*delim_k != '\0')
{
if(*str_next == *delim_k)
{
str_num = 1;
str_next++;
}
delim_k++;
}
if(str_num == 0)
{
break;
}
}
//str和str_next是不能同时为null的,其实“str是不能为空的”,但这里是因为strtok第二次开始调用时,传的参数为null,所以说第一次时str不能为null,第二次开始就可以为null,,因为str_next是记录调用后,置'\0'的后一个字符的地址,所以从第二次开始它不可能为null,所以说str和str_next是不能同时为null的,同时为空的情况只有第一次传str的地址进来时就为null,所以要避免此情况发生,当str_next不为空null也就代表它记录了“下一个字符串”的地址将它赋给str。
if(str == NULL)
{
if(str_next == NULL)
{
return NULL;
}
str = str_next;
}
//这是大多数人写的主代码,双层循环判断判断两个字符串是否有相同的字符,有就置'\0',如果只写这个,只适合被调用一次或者说只适合隔断符只有有一个,例如str=“192.168.2.1”中间只有一个字符“.”,,但如果多给它加几个字符,大多数人写的代码也就挂了,例如str=“192....168....2....1”时。
char *str_i = str;
while(*str_i != '\0')
{
char *delim_i = (char *)delim;
while(*delim_i != '\0')
{
if(*str_i == *delim_i)
{
*str_i = '\0';
str_next = str_i + 1; //记录置'\0'的后一个地址,准确的说是后一个字节地址,也就是下个字符的地址。
return str;
}
delim_i++;
}
str_i++;
}
//第一次没有在字符串str中找到和delim字符串中相同的字符,则还返回str,例1.str=“haha”、delim=“i” 此时虽然没有找到但仍要返回str、但如果在次或多次调用则返回null,例2.str=“zhang..san”、delim=“.” 此时虽然第一次能找到“.” ,但在次调用指针就指向字符“s”了,此时就和例1一样了。用static修饰n,防止n被释放。
static int n = 0;
n++;
if(n == 1)
{
return str;
}
else
{
return NULL;
}
}
//主函数试调
int main()
{
char a[] = "zhan1;.,.san2,..196";
char b[] = "123,456";
char c[] = ".,;";
char *ret = strtok(a, c);
printf("%s %s\n", a, ret);
printf("%p %p\n", a, ret);
printf("\n");
while(ret != NULL)
{
ret = strtok(NULL, c);
printf("%s %s\n", a, ret);
printf("%p %p\n", a, ret);
}
for(int i = 0; i < 19; i++)
{
printf("a + %d = %c\n", i, a[i]);
}
return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)