strtok和strtok_r函数的使用
strtok()和strtok_r()都是以特定字符串为分隔符来分隔源字符串,是属于string函数家的族函数。下面是基于实验得到的结论,实验环境为Linux Ubuntu11.04,gcc4.5.2。1. strtok()函数函数原型为:char *strtok(char *str, const char *delim);该函数的返回值是char型指针,也就是要返回分隔后的字符串。凡是返回指针的
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()函数的理解。
更多推荐
所有评论(0)