zoukankan      html  css  js  c++  java
  • C/C++ 字符串分割: strtok 与 strsep 函数说明

    函数原型:

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

                                char *strsep(char **s, const char *delim);

           功能:strtok和strsep两个函数的功能都是用来分解字符串为一组字符串。s为要分解的字符串,delim为分隔符字符串。

           返回值:从s开头开始的一个个子串,当没有分割的子串时返回NULL。

           相同点:两者都会改变源字符串,想要避免,可以使用strdupa(由allocate函数实现)或strdup(由malloc函数实现)。

    strtok函数第一次调用时会把s字符串中所有在delim中出现的字符替换为NULL。然后通过依次调用strtok(NULL, delim)得到各部分子串

    作用:
            分解字符串为一组字符串。s为要分解的字符串,delim为分隔符字符串。
    说明:
            strtok()用来将字符串分割成一个个片段。参数s指向欲分割的字符串,参数delim则为分割字符串,当strtok()在参数s的字符串中发现到参数delim的分割字符时则会将该字符改为 字符。在第一次调用时,strtok()必需给予参数s字符串,往后的调用则将参数s设置成NULL。每次调用成功则返回下一个分割后的字符串指针。
    返回值:
          从s开头开始的一个个被分割的串。当没有被分割的串时则返回NULL。
          所有delim中包含的字符都会被滤掉,并将被滤掉的地方设为一处分割的节点。(如下面的例子,可修改 seps里面的数据,然后看输出结果)

    #include <string.h>
    #include <stdio.h>
    char string[] ="A string	of ,,tokens
    and some  more tokens";
    char seps[]   =" ,	
    ";
    char *token;
    int main( void )
    {
       printf( "%s
    
    Tokens:
    ", string );
    /* Establish string and get the first token: */
       token = strtok( string, seps );
    while( token != NULL )
       {
    /* While there are tokens in "string" */
          printf( " %s
    ", token );
    /* Get next token: */
          token = strtok( NULL, seps );
       }
    return 0;
    }

    总结:

    strtok内部记录上次调用字符串的位置,所以不支持多线程,可重入版本为strtok_r,有兴趣的可以研究一下。它适用于分割关键字字符串之间“单独”或是 “连续“在一起的情况。

    strsep:

    #include <string.h>
    #include <stdio.h>
    char string[] ="A string	of ,,tokens
    and some  more tokens";
    char seps[]   =" ,	
    ";
    char *token, *s;
    int main( void )
    {
       printf( "%s
    
    Tokens:
    ", string );
    /* Establish string and get the first token: */
       s=string;
       token = strsep( &s, seps );
    while( token != NULL )
       {
    /* While there are tokens in "string" */
          printf( " %s
    ", token );
    /* Get next token: */
          token = strsep( &s, seps );
       }
    return 0;
    }

    为什么用strtok时子串中间没有出现换行,而strsep却有多个换行呢?文档中有如下的解释:

    One difference between strsep and strtok_r is that if the input string contains more
    than one character from delimiter in a row strsep returns an empty string for each
    pair of characters from delimiter. This means that a program normally should test
    for strsep returning an empty string before processing it.

        大意是:如果输入的串的有连续的多个字符属于delim,(此例source中的逗号+空格,感叹号+空格等就是这种情况),strtok会返回NULL而strsep会返回空串  ""。因而我们如果想用strsep函数分割字符串必须进行返回值是否是空串的判断。这也就解释了strsep的例子中有多个换行的原因。

    改进后的代码:

    效果:

    其中,  字符‘’  的 10进制数为0 , 宏定义为  NULL  。 

    下面的说明摘自于最新的Linux内核2.6.29,说明了strtok()已经不再使用,由速度更快的strsep()代替。

    /** linux/lib/string.c** Copyright (C) 1991, 1992 Linus Torvalds*/  

    /** stupid library routines.. The optimized versions should generally be found  

    * as inline code in <asm-xx/string.h>  

    * These are buggy as well..  

    * * Fri Jun 25 1999, Ingo Oeser <ioe@informatik.tu-chemnitz.de>  

    * - Added strsep() which will replace strtok() soon (because strsep() is  

    * reentrant and should be faster). Use only strsep() in new code, please.  

    ** * Sat Feb 09 2002, Jason Thomas <jason@topic.com.au>,  

    * Matthew Hawkins <matt@mh.dropbear.id.au>  

    * - Kissed strtok() goodbye

    */

    总结:

    strsep返回值为分割后的开始字符串,并将函数的第一个参数指针指向分割后的剩余字符串。它适用于分割关键字在两个字符串之间只严格出现一次的情况。

    PS:

    因为函数内部会修改原字符串变量,所以传入的参数不能是不可变字符串(即文字常量区)。

    如 char *tokenremain ="abcdefghij"//编译时为文字常量,不可修改。

    strtok(tokenremain,"cde");

    strsep(&tokenremain,"cde");

    编译通过,运行时会报段错误

  • 相关阅读:
    idea actiBPM插件之中文乱码
    quartz 集成到Spring中
    Spring 中将service 注入到普通的工具类中
    idea 将java 项目 打包成jar包
    异常来自 HRESULT:0x80070057 (E_INVALIDARG))
    Entity Framework小知识
    C# Unix时间戳转换
    Asp.NET MVC+WebAPI跨域调用
    位运算逻辑与逻辑或逻辑非运算 c# 中如何使用
    c# 学习笔记 重载、重写、重构、构造函数、new、Class
  • 原文地址:https://www.cnblogs.com/devilmaycry812839668/p/6353912.html
Copyright © 2011-2022 走看看