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

会修改数据源。外部加锁才线程安全(strtok执行结束再解锁执行另一个strtok循环知道工作完成)

主要是以互斥访问strtok实现文件中的static外部变量char*old。源码如下。

  1. #include <string.h>
  2.  
  3. static char *olds;
  4.  
  5. #undef strtok
  6.  
  7. /* Parse S into tokens separated by characters in DELIM.
  8. If S is NULL, the last string strtok() was called with is
  9. used. For example:
  10. char s[] = "-abc-=-def";
  11. x = strtok(s, "-"); // x = "abc"
  12. x = strtok(NULL, "-="); // x = "def"
  13. x = strtok(NULL, "="); // x = NULL
  14. // s = "abc\0=-def\0"
  15. */
  16. char *
  17. strtok (s, delim)
  18. char *s;
  19. const char *delim;
  20. {
  21. char *token;
  22.  
  23. if (s == NULL)
  24. s = olds;
  25.  
  26. /* Scan leading delimiters. */
  27. s += strspn (s, delim);
  28. if (*s == '\0')
  29. {
  30. olds = s;
  31. return NULL;
  32. }
  33.  
  34. /* Find the end of the token. */
  35. token = s;
  36. s = strpbrk (token, delim);
  37. if (s == NULL)
  38. /* This token finishes the string. */
  39. olds = __rawmemchr (token, '\0');
  40. else
  41. {
  42. /* Terminate the token and make OLDS point past it. */
  43. *s = '\0';
  44. olds = s + ;
  45. }
  46. return token;
  47. }

char *strsep(char **stringp, const char *delim)

会修改数据源。可重入的,注意这里虽然改动stringp的内容,主要是不在使用static静态变量了。

  1. #include <string.h>
  2.  
  3. #undef __strsep
  4. #undef strsep
  5.  
  6. char *
  7. __strsep (char **stringp, const char *delim)
  8. {
  9. char *begin, *end;
  10.  
  11. begin = *stringp;
  12. if (begin == NULL)
  13. return NULL;
  14.  
  15. /* A frequent case is when the delimiter string contains only one
  16. character. Here we don't need to call the expensive `strpbrk'
  17. function and instead work using `strchr'. */
  18. if (delim[] == '\0' || delim[] == '\0')
  19. {
  20. char ch = delim[];
  21.  
  22. if (ch == '\0')
  23. end = NULL;
  24. else
  25. {
  26. if (*begin == ch)
  27. end = begin;
  28. else if (*begin == '\0')
  29. end = NULL;
  30. else
  31. end = strchr (begin + , ch);
  32. }
  33. }
  34. else
  35. /* Find the end of the token. */
  36. end = strpbrk (begin, delim);
  37.  
  38. if (end)
  39. {
  40. /* Terminate the token and set *STRINGP past NUL character. */
  41. *end++ = '\0';
  42. *stringp = end;
  43. }
  44. else
  45. /* No more delimiters; this is the last token. */
  46. *stringp = NULL;
  47.  
  48. return begin;
  49. }

注意事项,会多次出现空字符串的问题,这是因为strsep在处理多于一个的delimit字符是会返回空字\0符串代替NULL(见源码便知),http://blog.csdn.net/striver1205/article/details/25601885

对比strtok,man手册提到:

The strsep() function was introduced as a replacement for strtok(3), since the latter cannot handle empty fields.
However, strtok(3) conforms to C89/C99 and hence is more portable.

stringp必须是二级指针,不能是指向字符数组的指针!

正确用法:

char a[]=......;char *p=a;strsep(&p,delim)

错误用法:

char a[]=...;strsep(&a,delim);会包参数类型错误

错误用法:

char *a=”xxxxx”;strsep(&a,delim)//错误,注意原串会被修改内容,字符常量会seg fault

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

会修改数据源。可重入,理由和strsep类似。

strsep和strtok_r替代strtok的更多相关文章

  1. 【C】——strtok()和strtok_r()

    下面的说明摘自于最新的Linux内核2.6.29,说明了strtok()这个函数已经不再使用,由速度更快的strsep()代替 /** linux/lib/string.c** Copyright ( ...

  2. C/C++ 字符串分割: strtok 与 strsep 函数说明

    函数原型: char *strtok(char *s, const char *delim); char *strsep(char **s, const char *delim); 功能:strtok ...

  3. 内存及字符串操作篇strlen strchar strcmp strcoll strcpy strdup strstr strtok strspn strrchr bcmp bcopy bzero index memccpy memset

    bcmp(比较内存内容) 相关函数 bcmp,strcasecmp,strcmp,strcoll,strncmp,strncasecmp 表头文件 #include<string.h> 定 ...

  4. C++常用字符串分割方法

    一.用strtok函数进行字符串分割 原型: char *strtok(char *str, const char *delim); 功能:分解字符串为一组字符串. 参数说明:str为要分解的字符串, ...

  5. C对字符串的部分操作

    字符串分割(C++)   经常碰到字符串分割的问题,这里总结下,也方便我以后使用. 一.用strtok函数进行字符串分割 原型: char *strtok(char *str, const char ...

  6. 字符串分割(C++)(转载)

    转载出自:http://www.cnblogs.com/MikeZhang/archive/2012/03/24/MySplitFunCPP.html 经常碰到字符串分割的问题,这里总结下,也方便我以 ...

  7. C++ 分割字符串两种方法

    原文地址:http://blog.csdn.net/xjw532881071/article/details/49154911 字符串切割的使用频率还是挺高的,string本身没有提供切割的方法,但可 ...

  8. 字符串分割(C++)

    一.用strtok函数进行字符串分割 原型: char *strtok(char *str, const char *delim); 功能:分解字符串为一组字符串. 参数说明:str为要分解的字符串, ...

  9. C++常用字符串分割方法(转)

    1.用strtok函数进行字符串分割 原型: char *strtok(char *str, const char *delim); 功能:分解字符串为一组字符串. 参数说明:str为要分解的字符串, ...

随机推荐

  1. Frameset框架

    总结一下.通过使用Frameset框架,可以在同一个浏览器窗口中显示不止一个页面. 先举个例子: <frameset rows="> <frame src="to ...

  2. NFS服务器配置文档

    Server:192.168.1.206/WindowsClient:192.168.1.208/CentOS一.搭建windows NFS服务:1.安装NFS服务器:打开"服务管理器&qu ...

  3. theano sparse_block_dot

    theano 中的一个函数 sparse_block_dot; Function: for b in range(batch_size): for j in range(o.shape[1]): fo ...

  4. js浏览器对象模型(BOM)

    浏览器对象模型(Browser Object Model,BOM):浏览器为js提供的对象集合. 1 windows对象 windows对象:表示浏览器的框架以及与其相关的内容,比如滚动条和导航栏图标 ...

  5. R for循环之break,next

    next跳出本次循环 break跳出本层循环(当有多个for 循环时,即跳出最近的一个for循环)

  6. Oracle 环境变量NLS_LANG

    NLS_LANG是一个环境变量,用于定义语言,地域以及字符集属性.对于非英语的字符集,NLS_LANG的设置就非常重要.NLS:'National Language Support (NLS)' 当我 ...

  7. php sleep

    实例一:把时间输出十次,但全部有结果了,才在html浏览器页面输出 ;$i<;$i++){ echo time()."<br>"; sleep(); } echo ...

  8. 《你不常用的c#之XX》

    你不常用的c#之一>:略谈unsafe http://blog.csdn.net/robingaoxb/article/details/6199508 <你不常用的c#之二>:略谈G ...

  9. SQL 从指定表筛选指定行信息 获取表行数

    1.获取指定表的行数 --获取表中数据行数 --select max([列名]) from 表名 2.筛选指定表的指定行数据(数据表分页获取) http://www.cnblogs.com/morni ...

  10. JDBC入门学习

    Introduction What's JDBC JDBC stands for Java Database Connectivity, which is a standard Java API fo ...