函数原型:
char * strtok(char * s,const char * ct)
使用第二个参数ct中的分隔符字符串,分割第一个参数s,ct参数的分隔符可以是任意字符,可以是单个字符的分隔符,也可以是字符串形式的分隔符如:"!,;'/"等,都可以作为分隔符。例如:
这个函数在分割一个字符串后,会将分隔符改为\0的。因此再次调用时,用NULL来代替字符串。
s="abc,def,123;456!/aaa"
ct=",;!/"s将被分割为为:abc def 123 456 aaa
测试代码:
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- int main()
- {
- char s[] = "abc,def,123;456!/aaa";
- char delim[] = " ,;!/";
- char *p = NULL;
- for(p = strtok(s, delim); p != NULL; p = strtok(NULL, delim))
- {
- printf("%s ", p);
- }
- printf("\n");
- return 0;
- }
[ljq@ycy algorithm]$ ./strtok
abc def 123 456 aaa
2. strtok代码分析,以下代码摘自Linux2.01.版本:
- char * strtok(char * s,const char * ct)
- {
- char *sbegin, *send;
- sbegin = s ? s : ___strtok;
- if (!sbegin) {
- return NULL;
- }
- sbegin += strspn(sbegin,ct);
- if (*sbegin == '\0') {
- ___strtok = NULL;
- return( NULL );
- }
- send = strpbrk( sbegin, ct);
- if (send && *send != '\0')
- *send++ = '\0';
- ___strtok = send;
- return (sbegin);
- }
先说下strtok的整体思想也就是关键的几个步骤:
a。首先strtok将数据保存在全局变量__strtok中,因此不是线程安全的也即不可重入。
b。strtok查找分隔符字符串时,跳过连续的分隔符,这样可以忽略连续分隔符之间的空串,连续分隔符是从源字符串开始位置计算,个数通过函数strspn计算得出。
size_t strspn(const char *s, const char *accept),计算字符串 str 中连续有几个字符都属于字符串 accept。
例如:";,/!ABC!/DEF",前四个字符都是分隔符且是连续的,那么strspn函数返回4,有效数据跳过前4个分隔符就从字符A开始,直到下一分隔符。
c。调用函数strpbrk,即源字符串中的字符如果与分隔符字符串中任意字符相同,就返回指向源字符串中该字符的指针,即找到了分隔符,返回该数据的指针。
char * strpbrk(const char * cs,const char * ct),比较字符串str1和str2中是否有相同的字符,如果有,则返回该字符在str1中的位置的指针。
例如:";,/!ABC!/DEF",跳过4个分隔符后,从A开始直到遇到分隔符感叹号(!) 那么,就返回指向数据起始位置的指针,该指针指向字符A。
细节分析:
a。 变量__strtok是全局变量,定义在string.c文件中:char * ___strtok = NULL; 在头文件linux/string.h中进行外部声明,只要使用该变量的c文件包含该头文件即可;
b。全局变量__strtok保存了剩余未做分隔的字符串的起始地址,每次调用strtok函数,都从全局变量__strtok指向的地址开始查找参数中的分隔符字符串,找到之后__strtok指向本次分隔符的下一位置(有效数据或者结尾符\0,又或者是分隔符如果有连续分隔符的话)。
c。对于字符串 "abc,def,123;456!/aaa"; 第一次调用strtok之后,分隔符逗号(,)被设置为\0,__strtok设置为指向第一个分隔符逗号之后的数据即__strtok指向字符d,返回指向字符a的指针;第二次调用strtok时,从__strtok指向的字符d开始查找delim中的分隔符,找到第二个逗号时,与第一次操作一样,分隔符逗号被设置为\0,并从新设置__strtok指向字符1,返回指向字符d的指针,后续一直如此循环。
d。如果源字符串包含连续分隔符,则调用函数strspn计算出连续相同的分隔符字符后会跳过这些分隔符。