![](https://i-blog.csdnimg.cn/blog_migrate/1baa3dae3f273018b18625b577c02c79.png)
1.strtok函数的参数和返回值
参数:第一个参数指定一个字符串,它包含了0个或者多个由del字符串中一个或者多个分隔符分割的标 记。
第二个参数del参数是个字符串,定义了用作分隔符的字符集合。
返回值:
如果找到分割符号,则指向分隔符号开头的指针。
否则为空指针。
当在正在扫描的字符串中到达字符串的末尾(即空字符)时,始终返回空指针。
2.VS库函数中的实现
extern "C" char* __cdecl __acrt_strtok_s_novalidation(
_Inout_opt_z_ char* string,
_In_z_ char const* control,
_Inout_ _Deref_prepost_opt_z_ char** context
);
extern "C" char* __cdecl strtok(char* const string, char const* const control)
{
return __acrt_strtok_s_novalidation(string, control, &__acrt_getptd()->_strtok_token);
}
3.strtok函数的使用
我们常常通过循环的方式来进行多次切割而得到想要的片段
以下是切割不当的错误示范
#define _CRT_SECURE_NO_WARNINGS 1
#include<string.h>
#include<stdio.h>
int main()
{
char arr1[] = "awsas%bda&adbajb*jwdjbsas@ahdb.awwqd";
char arr2[40];
//char arr2[] = "awsas%bda&adbajb*jwdjbsas@ahdb.awwqd";
strcpy(arr2, arr1);
char del[] = "%&*@.";
char* p = arr1;
p = strtok(arr2, del);
while (p!=NULL)
{
p = strtok(NULL, del);
printf("%s\n", p);
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/4b7606168df803bb800aeb3e7536d6b1.png)
这是正确的写法
#define _CRT_SECURE_NO_WARNINGS 1
#include<string.h>
#include<stdio.h>
int main()
{
char arr1[] = "awsas%bda&adbajb*jwdjbsas@ahdb.awwqd";
char arr2[40];
//char arr2[] = "awsas%bda&adbajb*jwdjbsas@ahdb.awwqd";
strcpy(arr2, arr1);
char del[] = "%&*@.";
char* p = arr1;
for(p = strtok(arr2, del);p!=NULL;p=strtok(NULL,del))
{
printf("%s\n", p);
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/8c3bb14a8a2577db66ab96596fbe958e.png)
4.strtok函数的模拟
在进行模拟之前我们先思考一个问题,,为什么每次函数被调用的时候,我们明明后续传入的是一个空指针,但是为什么却能够找到上一次保存的地址,c语言中有什么地方提供了这样的可能呢?没错,那就是静态变量。
4.1使用库函数
#include<stdio.h>
#include<assert.h>
#include<string.h>
char* my_strtok(char* str1, const char* str2)
{
assert(str2);
static int sz1 = NULL;
static int count = NULL;
static char* s1 = NULL;
static char* s2 = NULL;
int sz = 0;
if (str1 != NULL)
{
sz1 = strlen(str1);
s2 = str1;
sz = strlen(str2);
for (*str1; *str1 != 0; str1++)
{
for (int i = 0; i < sz; i++)
{
if (i == 0)
{
count++;
}
if (*str1 == *(str2 + i))
{
*str1 = 0;
s1 = str1;//记录这一次置0的位置。
return s2;
}
}
}
}
else
{
s2 = s1+1;
str1 = s2;
sz = strlen(str2);
for (*str1; *str1 != 0; str1++)
{
for (int i = 0; i < sz; i++)
{
if (i == 0)
{
count++;
}
if (*str1 == *(str2 + i))
{
*str1 = 0;
s1 = str1;
return s2;
}
}
}
if (count > sz1)
{
return NULL;
}
return s2;
}
}
int main()
{
char arr[20] = "adawa@wew%emm";
char* p = "@%";
char* str = NULL;
for (str = my_strtok(arr, p); str != NULL; str = my_strtok(NULL, p))
{
printf("%s\n", str);
}
return 0;
}
4.2或者不使用库函数进行实现
#define _CRT_SECURE_NO_WARNINGS 1
#include<string.h>
#include<stdio.h>
char* my_strtok(char* des, char* del)
{
char *des2 = des;
char *del2= del;
static char* p1 = NULL;
char* des3=NULL ;
if (des != NULL)
{
for (; *des2; des2++)
{
del2 = del;
for (; *del2; del2++)
{
if (*del2 == *des2)
{
*des2 = '\0';
p1 = des2;
p1++;
return des;
}
}
}
}
else
{
//des3 = p1;
for (; *p1; p1++)
{
del2 = del;
for (; *del2; del2++)
{
if (*del2 == *p1)
{
*p1 = '\0';
p1++;
return des3;
}
}
}
}
return NULL;
}
int main()
{
char arr1[] = "s&a%d&WAEA&HAHA";
char arr2[40];
//char arr2[] = "awsas%bda&adbajb*jwdjbsas@ahdbawwqd";
strcpy(arr2, arr1);
char del[] = "%&";
char* p = arr1;
//for(p = strtok(arr2, del);p!=NULL;p=strtok(NULL,del))
//{
// printf("%s\n", p);
//}
for(p = my_strtok(arr2, del);p!=NULL;p=my_strtok(NULL,del))
{
printf("%s\n", p);
}
}