c语言 strtok strtok_r的一种实现

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

char * strtok1(char *str, const char *delim)
{
    char *p = NULL;
    char *pd = NULL;
    static char *ps = NULL;
    char flag = 0;    //if ps not point to the last of str, set the flag = 1;

    if (str != NULL)
    {
        ps = str;
    }

    /* ignore the start delimeter of the token in the str */
    pd = (char *)delim;
    while (*pd != '\0')
    {
        if (*pd == *ps)
        {
            ps++;
            pd = (char *)delim;
        }
        else
        {
            pd++;
        }
    }
    p = ps;    
    
    /* find the token in the str */
    while (*ps != '\0')
    {
        pd = (char *)delim;
        while ((*pd != '\0') && (*pd != *ps))
        {
            pd ++;
        }    
        if (*pd == *ps)
        {
            *ps = '\0';
            ps++;
            return p;
        }
        else
        {    
            flag = 1;   //if input not contain delimeter we should return the string too.
            ps++;
        }
    }
    if (('\0' == *ps) && !flag)
    {
        ps = NULL;   //have already reach the end of the input sting, return NULL.
        return ps;
    }
    return p;  // return the string which not contain a delimeter.
}


/*******************************************************************************
because we will modification the input string.
can't define input string as: char *str = "root:x::0:root:/root:/bin/bash:";
str point to a constant string.
*******************************************************************************/
int main(void)
{
    char str[] = "root:x::0:root:/root:/bin/bash:";
    char str1[] = "root:x::0:root:/root:/bin/bash:";
    char *token;
    
    printf("%s\n", str);
    token = strtok(str, "/:");
    if (token != NULL)
        printf("%s\n", token);
    while ((token = strtok(NULL, "/:")) != NULL)
        printf("%s\n", token);

    printf("\n\n");
    token = strtok1(str1, "/:");
    if (token != NULL)
         printf("%s\n", token);
    while ((token = strtok1(NULL, "/:")) != NULL)
        printf("%s\n", token);
        
    return 0;   
}

/*****************************
output:
root:x::0:root:/root:/bin/bash:
root
x
0
root
root
bin
bash


root
x
0
root
root
bin
bash

*********************************/



/******************************************************************************
The  program  below uses nested loops that employ strtok_r() to break a
       string into a two-level hierarchy of tokens.   The  first  command-line
       argument specifies the string to be parsed.  The second argument speci‐
       fies the delimiter character(s) to be used to separate that string into
       "major"  tokens.   The  third  argument specifies the delimiter charac‐
       ter(s) to be used to separate the "major" tokens into subtokens.

       An example of the output produced by this program is the following:

        $ ./a.out 'a/bbb///cc;xxx:yyy:' ':;' '/'
        1: a/bbb///cc
         --> a
         --> bbb
         --> cc
        2: xxx
         --> xxx
        3: yyy
         --> yyy

        1: a/bbb///cc
         --> a
         --> bbb
         --> cc
        2: xxx
         --> xxx
        3: yyy
         --> yyy

*******************************************************************************/

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

char * strtok_r1(char *str, const char *delim, char **saveptr)
{
    char *p = NULL;
    char *pd = NULL;
    char flag = 0;

    if (str != NULL)
    {
        *saveptr = str;
    }
    /* ignore the start delimeter of the token in the str */
    pd = (char *)delim;
    while (*pd != '\0')
    {
        if (*pd == **saveptr)
        {
            (*saveptr)++;    // note: here use *saveptr++ is wrong!
            pd = (char *)delim;
        }
        else
        {            
            pd++;
        }
    }
    p = *saveptr;    
    
    /* find the token in the str */
    while (**saveptr!= '\0')
    {
        pd = (char *)delim;
        while ((*pd != '\0') && (*pd != **saveptr))
        {
            pd ++;
        }    
        if (*pd == **saveptr)
        {
            **saveptr = '\0';
            (*saveptr)++;   // note: here use *saveptr++ is wrong!
            return p;
        }
        else
        {
            flag = 1;
            (*saveptr)++;  // note: here use *saveptr++ is wrong!
        }
    }
    if (('\0' == **saveptr) && !flag)
    {
        *saveptr = NULL;
        return *saveptr;
    }
    return p;
}


int main(int argc, char *argv[])
{
   char *str1, *str2, *token, *subtoken;
   char *saveptr1, *saveptr2;
   int j;
   char arg1[] = "a/bbb///cc;xxx:yyy:";
   char arg2[] = ":;";
   char arg3[] = "/";        

   if (argc != 4)
    {
       fprintf(stderr, "Usage: %s string delim subdelim\n",
               argv[0]);
       exit(EXIT_FAILURE);
   }

   for (j = 1, str1 = argv[1]; ; j++, str1 = NULL)
    {
       token = strtok_r(str1, argv[2], &saveptr1);
       if (token == NULL)
           break;
       printf("%d: %s\n", j, token);

       for (str2 = token; ; str2 = NULL)
        {
            subtoken = strtok_r(str2, argv[3], &saveptr2);
           if (subtoken == NULL)
               break;
           printf(" --> %s\n", subtoken);
       }
   }
    
    putchar('\n');
    for (j = 1, str1 = arg1; ; j++, str1 = NULL)
    {
       token = strtok_r1(str1, arg2, &saveptr1);
       if (token == NULL)
           break;
       printf("%d: %s\n", j, token);

       for (str2 = token; ; str2 = NULL)
        {
           subtoken = strtok_r1(str2, arg3, &saveptr2);
           if (subtoken == NULL)
               break;
           printf(" --> %s\n", subtoken);
       }
   }
   exit(EXIT_SUCCESS);
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值