zoukankan      html  css  js  c++  java
  • strsep和strtok_r替代strtok

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

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

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

    #include <string.h>
    
    
    static char *olds;
    
    #undef strtok
    
    /* Parse S into tokens separated by characters in DELIM.
       If S is NULL, the last string strtok() was called with is
       used.  For example:
            char s[] = "-abc-=-def";
            x = strtok(s, "-");             // x = "abc"
            x = strtok(NULL, "-=");         // x = "def"
            x = strtok(NULL, "=");          // x = NULL
                    // s = "abc=-def"
    */
    char *
    strtok (s, delim)
         char *s;
         const char *delim;
    {
      char *token;
    
      if (s == NULL)
        s = olds;
    
      /* Scan leading delimiters.  */
      s += strspn (s, delim);
      if (*s == '')
        {
          olds = s;
          return NULL;
        }
    
      /* Find the end of the token.  */
      token = s;
      s = strpbrk (token, delim);
      if (s == NULL)
        /* This token finishes the string.  */
        olds = __rawmemchr (token, '');
      else
        {
          /* Terminate the token and make OLDS point past it.  */
          *s = '';
          olds = s + 1;
        }
      return token;
    }
    View Code

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

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

    #include <string.h>
    
    #undef __strsep
    #undef strsep
    
    char *
    __strsep (char **stringp, const char *delim)
    {
      char *begin, *end;
    
      begin = *stringp;
      if (begin == NULL)
        return NULL;
    
      /* A frequent case is when the delimiter string contains only one
         character.  Here we don't need to call the expensive `strpbrk'
         function and instead work using `strchr'.  */
      if (delim[0] == '' || delim[1] == '')
      {
          char ch = delim[0];
    
            if (ch == '')
                end = NULL;
             else
            {
                if (*begin == ch)
                    end = begin;
                else if (*begin == '')
                    end = NULL;
                else
                    end = strchr (begin + 1, ch);
            }
      }
      else
        /* Find the end of the token.  */
        end = strpbrk (begin, delim);
    
      if (end)
      {
          /* Terminate the token and set *STRINGP past NUL character.  */
          *end++ = '';
          *stringp = end;
      }
      else
        /* No more delimiters; this is the last token.  */
        *stringp = NULL;
    
      return begin;
    }
    View Code

    注意事项,会多次出现空字符串的问题,这是因为strsep在处理多于一个的delimit字符是会返回空字符串代替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类似。

  • 相关阅读:
    css布局
    css笔记
    css笔记
    css笔记
    HttpServletResponse简单理解
    SpringCloud Zuul网关的简单理解
    SpringCloud Zuul网关超时
    notepad++实用技巧
    Json常用代码
    含有Date属性的对象转化为Json
  • 原文地址:https://www.cnblogs.com/zhaoyl/p/5774134.html
Copyright © 2011-2022 走看看