发现了一个奇怪的函数逻辑:
#include <string.h>
#include <stdio.h>
int main () {
char str[80] = "This is - www.runoob.com - website";
const char s[2] = "-";
char *token;
/* 获取第一个子字符串 */
token = strtok(str, s);
/* 继续获取其他的子字符串 */
while( token != NULL ) {
printf( "%s\n", token );
token = strtok(NULL, s);
}
return(0);
}
运行结果如下:
疑问在于,为什么strtok()这个函数在获取第一个子字符串之后需要设置一下strtok(NULL, s)呢?
百思不得其解的去查了查这个函数的原型以及解释:
strtok()字符串分割函数
一、函数原型
char *strtok(char s[], const char *delim)
二、参数及返回值说明
名称 | 作用 |
---|---|
s[] | 要分解的字符串 |
*delim | 分割字符,如果传入的是字符串,则字符串包含的每个字符均为分隔符 |
返回值 | 返回被分解的第一个子字符串,如果没有可检索的字符串,则返回一个空指针 |
三、思考与实践
关于在函数的参数和返回值里没获得解决疑问的关键,我决定自己动手试一试。先来看看在截取了第一次子字符串之后,原字符串变成什么了
#include <string.h>
#include <stdio.h>
int main () {
char str[80] = "This is - www.runoob.com - website";
const char s[2] = "-";
char *token;
/* 获取第一个子字符串 */
token = strtok(str, s);
printf("%s\n",token);
printf("%s\n",str);
return(0);
}
神奇的事情发生了,原字符串剩下的部分去哪儿了?:
四、查阅资料
查询资料后发现strtok函数执行过程有这样几个重点:
- 当strtok()在参数s的字符串中发现参数delim中包含的分割字符时,则会将该字符改为\0 字符。
- 在第一次调用时,strtok()必需给予参数s字符串,往后的调用则将参数s设置成NULL。
- 每次调用成功则返回指向被分割出片段的指针。
- 使用该函数进行字符串分割会破坏被分解字符串的完整
- 第一次分割之后,原字符串变为了分割完成之后的第一个字符串,剩余的字符串存储在一个静态变量中,因此多线程同时访问该静态变量时,则会出现错误。
五、扩展
为了保证数据的安全性,人们想出了很多的办法,在此分割函数的基础上构建了很多新的函数。例如;
-
strtok_s
strtok_s是windows下的一个分割字符串安全函数,函数原型:
char *strtok_s( char *strToken, const char *strDelimit, char **buf);
该函数将剩余的字符串存储在buf变量中,而不是静态变量中,从而保证了安全性。 -
strtok_r
strtok_r是linux下的一个分割字符串安全函数,函数原型:
char *strtok_r(char *str, const char *delim, char **saveptr);
该函数将剩余的字符串存储在saveptr变量中,保证了安全性。
分享就到这里,感谢观看。
“写程序,不比其它的学科,动手才是硬道理。” ——绝影Hamber