strtok函数及函数实现
strtok()用来将字符串分割成一个个片段。参数str指向欲分割的字符串,参数delimiters则为分割字符串,当strtok()在参数str的字符串中发现到参数delimiters的分割字符时则会将该字符改为'\0'字符。在第一次调用时,strtok()必需给予参数str字符串,往后的调用则将参数str设置成NULL。每次调用成功则返回下一个分割后的字符串指针。
返回值
返回下一个分割后的字符串指针,如果已无从分割则返回NULL。
示例-1
/* strtok example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="a,b,c,d*e";
const char * split = ",";
char * p;
p = strtok (str,split);
while(p!=NULL) {
printf ("%s\n",p);
p = strtok(NULL,split);
}
getchar();
return 0;
}
本例中,实现对字符串'a,b,c,d*e"用逗号(,)来作界定符对字符串进行分割。
输出结果将如下所示:
a
b
c
d*e
因为delimiters支持多个分割符, 我们将本示例中的语句行
const char * split = ",";
改成 const char * split = ",*"; //用逗号(,)和星号(*)对字符串进行分割
这样输出结果将如下所示:
a
b
c
d
e
strtok函数的源码如下:
char *___strtok;//关键这个全局指针变量
char * strtok(char * s,const char * ct)
{
char *sbegin, *send;
sbegin = s ? s : ___strtok;//不等于NULL用原始字符串,否则用___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);
}
其中: ssize_t strspn(const char* s,char*accept)// 函数说明 strspn()从参数s 字符串的开头计算连续的字符,而这些字符都完全是accept 所指字符串中的字符。简单的说,若strspn()返回的数值为n,则代表字符串s 开头连续有n 个字符都是属于字符串accept内的字符。
char * strpbrk(const char * cs,const char * ct)//返回指向ct中任一字符在cs中第一次出现的位置
这个函数不难分析,___strtok指针指向除去第一个有效字串后面的位置,到这里我们应该清楚为什么第二次调用时只要传NULL就可以了,当然这里也暴露了它的缺点,就是说不能有两个线程同时使用strtok否则就会出现错误
+----------------+
| strtol |
+----------------+
i.e. string tolong
long intstrtol(const char *nptr, char **endptr, int base)
strtol()会将nptr指向的字符串,根据参数base,按权转化为longint,然后返回这个值。
参数base的范围为2~36,和0;它决定了字符串以被转换为整数的权值。
可以被转换的合法字符依据base而定,举例来说,当base为2时,合法字符为‘0’,‘1’;base为8时,合法字符为‘0’,‘1’,……‘7’;base为10时,合法字符为‘0’,‘1’,……‘9’;base为16时,合法字符为‘0’,‘1’,……‘9’,‘a’,……‘f’;base为24时,合法字符为‘0’,……‘9’,‘a’,……‘n’,base为36时,合法字符为‘0’,……‘9’,‘a’,……‘z’;等等。其中,不区分大小写,比如,‘A’和‘a’会都会被转化为10。
当字符合法时,‘0’,……‘9’依次被转换为十进制的0~9,‘a’,……‘z’一次北转换为十进制的10~35。
strtol()函数检测到第一个非法字符时,立即停止检测,其后的所有字符都会被当作非法字符处理。合法字符串会被转换为long int,作为函数的返回值。非法字符串,即从第一个非法字符的地址,被赋给*endptr。**endptr是个双重指针,即指针的指针。strtol()函数就是通过它改变*endptr的值,即把第一个非法字符的地址传给endptr。
多数情况下,endptr设置为NULL,即不返回非法字符串。
下面看几个例子:
------------------------------------------------------
char buffer[20]="10379cend$3";
char *stop;
printf("%d\n",strtol(buffer, &stop, 2));
printf("%s\n", stop);
输出结果:
2
379cend$3
-------------------------------------------------------
char buffer[20]="10379cend$3";
char *stop;
printf("%d\n",strtol(buffer, &stop, 8));
printf("%s\n", stop);
输出结果:
543
9cend$3
--------------------------------------------------------
char buffer[20]="10379cend$3";
char *stop;
printf("%d\n",strtol(buffer, &stop, 10));
printf("%s\n", stop);
输出结果:
10379
cend$3
-------------------------------------------------------
char buffer[20]="10379cend$3";
char *stop;
printf("%d\n",strtol(buffer, &stop, 16));
printf("%s\n", stop);
输出结果:
17005006
nd$3
另外,如果base为0,且字符串不是以0x(或者0X)开头,则按十进制进行转化。如果base为0或者16,并且字符串以0x(或者0X)开头,那么,x(或者X)被忽略,字符串按16进制转化。如果base不等于0和16,并且字符串以0x(或者0X)开头,那么x被视为非法字符。
例如:
-------------------------------------------------------
char buffer[20]="0x31da6c";
char *stop;
printf("%d\n",strtol(buffer, &stop, 0));
printf("%s\n", stop);
输出结果(stop为空):
3267180
-------------------------------------------------------
char buffer[20]="0x31da6c";
char *stop;
printf("%d\n",strtol(buffer, &stop, 13));
printf("%s\n", stop);
输出结果:
0
0x31da6c
-------------------------------------------------------
最后,需要说明的是,对于nptr指向的字符串,其开头和结尾处的空格被忽视,字符串中间的空格被视为非法字符。
例如:
-------------------------------------------------------
char buffer_1[20]="10379c";
char buffer_2[20]=" 10379c ";
char buffer_3[20]=" 10 379c ";
printf("%d\n",strtol(buffer_1,NULL,0));
printf("%d\n",strtol(buffer_2,NULL,0));
printf("%d\n",strtol(buffer_3,NULL,0));
输出结果为:
10379
10379
10