strtok函数和可重入函数strtrok_s、strtok_r的使用和注意事项

目录

strtok函数——按照指定的分隔符将字符串分割

内部实现机制:

strtok函数缺点:

解决方法:可重入函数(线程安全函数)

strtok_s、strtok_r


strtok函数——按照指定的分隔符将字符串分割

函数原型:

char *strtok(char s[], const char *delim)
参数一:要被分割的字符串
参数二:指定的分隔符

内部实现机制

实例:

#include
#include

int main()
{
    char buff[]="asd,sdf,dfg";
    char *p=NULL;
    p=strtok(buff,",");
    while(p!=NULL)
    {
        ptintf("%s\n",p);
        p=strtok(NULL,",");
    }
}

运行结果:
asd
sdf
dfg

strtok会从buff的首地址开始找分隔符“,”,找到后就会将“,”置换为"\0",并记住这个位置——内部会有一个静态变量指针指向此位置,以便于下一次分割。然后返回”\0“前的字符串的首地址。此时buff中字符串为:”asd\0sddf,dfg“

第二次调用strtok时,因为有静态变量指针记住了上一次分割的位置,所以参数一输入NULL占位即可(因为指针记住的这个位置刚好是\0所以就是NULL),从指针指向的下一个地址”s“开始找分隔符,找到后继续将”,“置换为”\0“,返回本次分割好的字符串首地址。此时buff中字符串为:”asd\0sddf\0dfg“

...以此循环

直到最后一次调用strtok时,此时静态变量指针指向”asd\0sddf\0dfg\0“字符串末尾(标黄的\0),返回空,至此strtok函数结束分割。

注意事项:1.strtok函数在进行字符串分解的时候,其第一个参数buff是在变化的,将分隔符都置换为“\0”,改变了源字符串。strtok函数的第一个参数是一个指针,如果该指针是字符串常量的指针,就会引起程序运行崩溃,因为源字符串要发生变化,而字符串常量不能被改变。虽然可以将字符串常量先拷贝到一个字符串数组中再使用strtok函数进行分割,但效率低,不建议这样使用。

2.  对于strtok函数的第二个参数分隔符,可传入的参数是const char *delim,是一个字符串,那么包含在delim中的字符均可以作为分隔符,而非严格匹配。可以把delim理解为分隔符的集合。这一点是非常重要的!当然,我们在分解字符串的时候,很少使用多个分隔符。

strtok函数缺点:

strtok函数中有静态变量指针用来保存下一次分割的地址,那就会导致多线程中,线程都去调用strtok函数时,共用进程中的静态变量,导致运行结果不正确。

解决方法:可重入函数(线程安全函数)

strtok_s、strtok_r

//windows下的可重入函数
char *strtok_s(char *strToken,const char *strDelimit,char **context);

//Linux下的可重入函数
char *strtok_r(char *str, const char *delim, char **saveptr);

//参数三使用二级指针,是因为函数内部的指针变量保存下一次要分割的位置,而每一次分割结束指针所指向的位置都会发生变化,所以使用二级指针要改变指针的内容/

原理:调用strtok的可重入函数版本都是没有使用静态变量指针,线程调用自己的strtok函数,函数中使用自己的指针变量(栈上开辟了空间)去保存下一次分割的起始位置,线程间就互不干扰。

你可能感兴趣的:(c语言,安全)