实现`strtok`,其分隔符有多个字符

时间:2015-04-24 12:47:03

标签: c delimiter strtok c-strings

代码段:

char str[] = "String1::String2:String3:String4::String5";
char *deli = "::";
char *token = strtok(str,deli);

while(token != NULL)
{
  printf("Token= \"%s\"\n", token);
  token=strtok(NULL,deli);
}

上面的代码片段产生输出:

Token="String1"
Token="String2"
Token="String3"
Token="String4"
Token="String5"

但我希望输出为:

Token="String1"
Token="String2:String3:String4"
Token="String5"

我知道我没有得到预期的输出,因为 strtok的第二个参数中的每个字符被视为分隔符。

为了获得预期的输出,我编写了一个程序,使用strstr(以及其他东西)将给定的字符串拆分为标记,以便获得预期的输出。这是程序:

#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

int myStrtok(char* str,char* deli)
{
    if(str==NULL || deli==NULL)
        return -1;

    int tokens=0;
    char *token;
    char *output=str;


    while((token=strstr(output,deli))!=NULL)
    {

        bool print=true;

        if(output != token)
        {
            printf("Token = \"");
            tokens++;
            print=false;
        }

        while(output != token)
        {
            putchar(*output);
            output++;
        }

        if(print==false)
            printf("\"\n");
        output+=strlen(deli);
    }

    if(strlen(output)>0)
    {
        printf("Token = \"%s\"",output);
        tokens++;
    }
    printf("\n\n");
    return tokens;
}

int main(void)
{
    char str[]="One:1:Two::Three::::";
    char *deli="::";

    int retval;
    printf("Original string=\"%s\"\n\n",str);

    if((retval=myStrtok(str,deli))==-1)
        printf("The string or the delimeter is NULL\n");
    else
        printf("Number of tokens=%d\n", retval);
    return(EXIT_SUCCESS);
}

上述程序产生预期的输出。

我想知道是否有更简单/更简单的方法。有没有?

3 个答案:

答案 0 :(得分:3)

一个字符串分隔符函数,它使用strtok的原型并模仿其用法:

char *strtokm(char *str, const char *delim)
{
    static char *tok;
    static char *next;
    char *m;

    if (delim == NULL) return NULL;

    tok = (str) ? str : next;
    if (tok == NULL) return NULL;

    m = strstr(tok, delim);

    if (m) {
        next = m + strlen(delim);
        *m = '\0';
    } else {
        next = NULL;
    }

    return tok;
}

答案 1 :(得分:1)

如果你不关心与{{1}}相同的使用方法,我会这样做:

{{1}}

答案 2 :(得分:0)

源自strsep https://code.woboq.org/userspace/glibc/string/strsep.c.html

的代码
char *strsepm( char **stringp, const char *delim ) {

    char *begin, *end;

    begin = *stringp;

    if  ( begin == NULL ) return NULL;

    /* Find the end of the token.  */
    end = strstr( begin , delim );

    if ( end != NULL ) {

        /* Terminate the token and set *STRINGP past NUL character.  */
        *end = '\0';

        end  += strlen( delim );

        *stringp = end;

    } else {

        /* No more delimiters; this is the last token.  */
        *stringp = NULL;  
    }

    return begin;
}

int main( int argc , char *argv [] ) {

    char            *token_ptr;
    char            *token;
    const char      *delimiter = "&&";

    char            buffer [ 256 ];

    strcpy( buffer , " && Hello && Bernd && waht's && going && on &&");

    token_ptr = buffer;

    while ( ( token = strsepm( &token_ptr , delimiter ) ) != NULL ) {

        printf( "\'%s\'\n" , token );

    }
}

结果:

' '   
' Hello '    
' Bernd '    
' waht's '    
' going '    
' on '    
''