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);
}





你可能感兴趣的:(c,String,null,语言,token,hierarchy)