#include <string.h>
char* strtok(char *str, const char *delim);
char* strtok_r(char *str, const char *delim, char **saveptr);
【函数描述】将字符串str分割成由delim指定的分隔符的字符串,返回分割后的字符串。第一次执行要以被分割的字符串为参数,之后要以NULL作为参数。
【函数说明】strtok_r是Linux平台下的strtok的线程安全版。Windows下的string.h文件并不包含它,Windows平台下是strtok_s()函数。strtok_r()比strtok()多了一个二级字符指针参数,它是用来在strtok_r()内部保存切割字符串后余下的字符串的首地址。实际上,strtok()函数也有一个这样的指针,不过它是被定义成了一个静态的指针变量来保存切分字符串后余下的字符串的首地址。而strtok_r()函数实际上是将strtok()内部隐式保存的这个静态指针以形参的形式与函数外部的实参进行交互。由调用者进行传递、保存甚至是修改。调用者在连续切分相同字符串时,除了将str参数赋值给NULL,还要传递上次切分时保存下来的saveptr。实际上,它是将切分后剩余字符串的首地址保存在外部的一个字符指针变量里,然后将这个指针变量的地址传递给形参saveptr。
函数的实现
//strtok_r()函数的实现,来自于glibc
/* Parse S into tokens separated by characters in DELIM.
If S is NULL, the saved pointer in SAVE_PTR is used as
the next starting point. For example:
char s[] = "-abc-=-def";
char *sp;
x = strtok_r(s, "-", &sp); // x = "abc", sp = "=-def"
x = strtok_r(NULL, "-=", &sp); // x = "def", sp = NULL
x = strtok_r(NULL, "=", &sp); // x = NULL
// s = "abc\0-def\0"
*/
char* strtok_r(char *s,const char *delim,char **save_ptr)
{
char *end;
if(s == NULL)
s = *save_ptr; //将上次切分后剩余字符串的首地址赋值给s
if(*s == '\0'){ //如果当前字符串为空,返回NULL
*save_ptr=s;
return NULL;
}
//过滤掉当前字符串开头的分隔符
s+=strspn(s,delim);
if(*s == '\0')
{
*save_ptr=s;
return NULL;
}
//找到分隔符的位置
end=s+strcspn(s,delim);
if(*end == '\0')
{
*save_ptr=end;
return s;
}
*end = '\0'; //将分隔符的位置用字符串结束符'\0'填充
*save_ptr=end+1; //*save_ptr指向分隔符的下一个字符
return s; //返回分割的字符串
}
//strtok()函数的实现
char* strtok (char *s, const char *delim)
{
static char *olds; //定义了一个局部静态字符指针变量
return strtok_r (s, delim, &olds);
}
<说明>上面的strtok_r()函数的实现用到了两个函数分别是strspn()和strcspn()函数。
#include <string.h>
size_t strspn(const char *s, const char *accept);
【函数描述】从参数s字符串的开头计算连续的字符,而这些字符都是accept字符串中的字符。返回字符串s开头
连续包含字符串accept中的字符数目。如果s所包含的字符都属于accept,那么返回s的长度;如果s的第一个字
符就不属于accept,那么返回0。注意,检索的字符是区分大小写的。
size_t strcspn(const char *s, const char *reject);
【函数描述】strcspn()函数的作用与strspn()函数的作用相反。它是计算字符串s中连续有几个字符都不属于字
符串reject,返回字符串s的开头连续不含有字符串reject内的字符的数目。
示例程序
1. strtok()函数示例程序。
#include <stdio.h>
#include <string.h>
int main()
{
char buffer[1024]="ss7Notify:5:1:15973362998";
char *str,*buf;
buf=buffer;
int i=0;
while((str = strtok(buf, ":")) != NULL)
{
printf("i=%d,%s\n",++i,str);
buf=NULL;
}
return 0;
}
运行结果:
i=1,ss7Notify
i=2,5
i=3,1
i=4,15972362632
2. strtok_r()函数示例程序。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char str[]="Legendary:Godlike:Dominating:Unstoppable:Rampage";
char *ps, *qs;
char *saveptr;
int i=0;
printf("before strtok_r(),str= %s\n",str);
printf("begin:\n");
ps=qs=str; //ps,qs指针初始指向str数组
for(; NULL != (ps = strtok_r(qs, ":", &saveptr)); ++i){
printf("i=%d, ps= %s\n", i, ps);
qs=NULL;
}
printf("end, item count: %d\n", i);
return 0;
}
运行结果:
before strtok_r(),str= Legendary:Godlike:Dominating:Unstoppable:Rampage
begin:
i=0, ps= Legendary
i=1, ps= Godlike
i=2, ps= Dominating
i=3, ps= Unstoppable
i=4, ps= Rampage
end, item count: 5