分割字符串的时候,一般想到用strtok,但是该函数使用时需要很小心,而且结果有的时候让人费解。
比如说网上这段代码:
比如,分隔符=“,” 字符串=“Fred,John,Ann” 通过strtok 就可以把3个字符串 “Fred” “John” “Ann”提取出来。 上面的C代码为
char buffer[]="Fred,John,Ann"
char *p[3];
char *buff = buffer;
while((p[in]=strtok(buf,","))!=NULL) {
in++;
buf=NULL; }如上代码,第一次执行strtok需要以目标字符串的地址为第一参数(buf=buffer),之后strtok需要以NULL为第一参数 (buf=NULL)。指针列p[],则储存了分割后的结果,p[0]="John",p[1]="John",p[2]="Ann",而buf就变 成 Fred\0John\0Ann\0。
使用
for(i=0; i<in ;i++)
printf("%s \n", p[i]);
程序的运行结果和你想的不一样,p[0]="",p[1]="John",p[2]="Ann",注意此时p[0]为空不是网上那样的答案。使用gdb查看循环里面的值,发现更让人费解。在while循环里面gdb查看p[0]的值,p[0]="John"一直如此,但是当程序退出循环时,p[0]发生了变化。
在这里我不得不吐槽以下中国的程序员缺乏认真的态度,总是转载东西,修改都不修改,比如说QUOTE里面的程序有很多处明显错误,都没有人去修改。比如把
buff 写成buf,缺分号啥的,等等。
还有就是更无语的,http://zhwen.org/tools/clib/string/strtok.html该网址里面是介绍一些库函数,给的所谓的案例程序明显就是错误的,无法运行的,有段错误。因为strtok的实现机制修改了传入字符串内容,
char *s="Golden Global View";这个使用的字符常量,是不可修改的。应该使用数组,数组是放在栈上的。
网上找了资料,发现什么strtok,strtok_r的区别啊,在于代码的可插入,最后找到亮点了发现linux早就有更好的实现即strsep,该函数不仅可重入,且运行效率更快,更好使用。
strsep(),作为strtok的升级版,是一个很有用的字符串处理函数, 但是也有很多不方便的地方, 使用时需特别小心, 好在注意的事项都在 man strsep 里面有。如下:
#include <string.h>
char *strsep(char **stringp, const char *delim);
Be cautious when using this function. If you do use it, note that: * This function modifies its first argument.
* This function cannot be used on constant strings.
* The identity of the delimiting character is lost.
自己写了一个小程序测试以下
#include <string.h> #include <stdio.h> #include <stdlib.h> #define MAX 5 int main(int arg, const char *argv[]) { int in=0; char* string = strdup( "/home/yinlijun/project:/home/yinlijun:/home/someone"); /*字符串不能为常量,所以strdup*/ char *p[MAX]; while((p[in] = strsep(&string, ":")) != NULL) /*第一个参数设为二级指针, 字符串中所有的第二个参数(子串)最后会被替代成‘/0’*/ { in++; } int i; for(i=0; i < in ;i++ ) printf("%s\n", p[i]); free(string); return 0; }
<span style="font-family: Arial, Helvetica, sans-serif;">总之,一句话,网上找资料真的是太麻烦了,很多人几乎就是原样转载。</span>