strtok和strtok_r函数的使用

strtok()和strtok_r()都是以特定字符串为分隔符来分隔源字符串,是属于string函数家的族函数。

下面是基于实验得到的结论,实验环境为Linux Ubuntu11.04,gcc4.5.2。

1. strtok()函数

函数原型为:

char *strtok(char *str, const char *delim);

该函数的返回值是char型指针,也就是要返回分隔后的字符串。

凡是返回指针的函数,可以推断该指针变量:

1) 通过malloc在函数中动态分配的。这类函数要注意调用完毕后手动free。鉴于这是一个库函数,若需要程序员调用
完该API后手动free,显得十分繁琐,所以这个返回的指针变量不是strtok函数中动态生成。

2) 返回形参的变量的地址。strtok的形参分别是指向待分解的源字符串和分隔符,返回形参的地址也不符合函数功
能。

3) 返回全局变量的地址。换句话说strtok把分割后的字符串放在一个全局变量中,并且把该地址返回给API调用者,确
实如此。

strtok()的使用方法是以*delim为分隔符,若str不为NULL,则查找str的第一个分隔符,将分隔符替换为’\0’,分隔符
前的字符串的首地址a和分隔符后的字符串的首地址b赋值给它自己维护的全局变量,并且返回该全局变量的b的地址;
若str为NULL,那么strtok()查找的起始位置则是自身维护的地址变量,它保存的是上次查找的分隔符后的首个元素的
地址。

验证程序: 分离/etc/passwd/文件中首行字符串。/etc/passwd是Linux记录用户名及密码的文件,在我的开发环境的
该文件的首行字符串为:

root:x:0:0:root:/root:/bin/bash

以”:”为分隔符,得到的字符串共有7个。

int main(void)
{
    FILE *fp = NULL;
    char buf[1024] = {};
    char *p = NULL;
    int i = 0;
    char *info[8] = {};

    //只读方式打开文件
    fp = fopen("/etc/passwd", "r");
    if (NULL == fp)
    {
        perror("perror");
        return -1;
    }

    //获取fp指向的文件的一行字符串
    fgets(buf, sizeof(buf), fp);
    printf("fgets: %s", buf);

    p = buf;  //首次调用,要先把源字符串传进去
    //非首次调用,p为NULL传进去后,strtok会去自身备份的地址信息接着上一次的查找位置查找
    //每一次查找strtok返回的是分隔符前面的字符串的首地址
    while ((info[i++] = strtok(p, ":")) != NULL)  
        p = NULL;

    printf("buf = %s\n", buf);  

    for (i = 0; i < 7; i++){
        printf("info[%d] = %s\n", i, info[i]);
    }

    fclose(fp);
    return 0;
}

运行结果:
这里写图片描述

用表格的形式表现strtok的工作流程为:
这里写图片描述

2. strtok_r()函数

strtok()函数是不可重入的,即在分隔一个字符串期间,函数返回后若去分隔另一个字符串,那么上一次的全局地址信息就会被覆盖。strtok_r()则是可重入的。原型为:

char *strtok_r(char *str, const char *delim, char **saveptr);

参数3是一个二级指针,也就是存放一级指针的地址。strtok_r同样是返回指针变量,与strtok不同的是,返回的地址
值不再是全局变量的地址,而是参数saveptr所指向的空间的地址了,该空间存放的是本次调用后分隔符前的字符串的
首地址。注意每次对strtok_r的调用都是针对形参str所指向的字符串。这样一来,API调用者可以自己在主调函数中维
护备份第3个实参了。

利用strtok_r()来实现上述功能为:

int main(void)
{
    FILE *fp = NULL;
    char buf[1024] = {};
    char *p = NULL;
    int i = 0;
    char *info[8] = {};

    //只读方式打开文件
    fp = fopen("/etc/passwd", "r");
    if (NULL == fp)
    {
        perror("perror");
        return -1;
    }

    //获取fp指向的文件的一行字符串
    fgets(buf, sizeof(buf), fp);
    printf("fgets: %s", buf);

    info[0] = buf;
    for (i = 0; i < 8; i++)
    {
        info[i] = strtok_r(info[i], ":", &info[i + 1]);
    }

    for (i = 0; i < 7; i++)
    {
        printf("info[%d] = %s\n", i, info[i]);
    }

    fclose(fp);
    return 0;
}

运行结果:
这里写图片描述

用表格的形式表现strtok_r的工作流程为:
这里写图片描述
上述便是我对strtok()和strtok_r()函数的理解。

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值