Rewriting strtok

I stayed up late last night trying to complete an assignment. The assignment seems to want me to rewrite the strtok function, but my grasp on pointer manipulation is far from firm. I looked and looked for answers on the internet, but most of the search results are about USING strtok instead of rewriting it.

I managed to come up with something, but I have a feeling it's not right at all. I'm not asking you to do my homework. I just need some critique and a nudge in the right direction, please.

Assignment URL: http://comp.uark.edu/~wingning/csce2014/homework1.pdf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
char *mystrtok(char *str, const char *delim)
{
    static char *last;
    char *final;
    int i=0; 
    if(*str!=NULL)
    {
        while(str!=delim)
        {
            final[i]=str[i];
            *str++;
        }
        *last=*str;
    }
    
    else if(*str==NULL)
    {
        while(last!=delim)
        {
            final[i]=last[i];
            *str++;
        }
    }
    i=0;
    return final;
}


Any feedback would be greatly appreciated.
str is the pointer and *str gives you the character it is pointing to.
You have it backwards everywhere. final isn't pointing to anything either and besides, there is no need to rewrite the string.
After a little pointer study, I rewrote my function. I realize there are some flexibility issues, but I'm trying to get the concept down first.

What I don't understand is how the returned pointer still has something to point to. The array that it pointed to was in the scope of the function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>
using namespace std;
char *mystrtok(char *str, const char *delim);
int main()
{
    char * end;
    char str[] = "Here is a string";
        cout << str << endl;
        mystrtok(str, " ");
        cout << "end: " << end;
        return 0;
}


char *mystrtok(char *str, const char *delim)
{
     static char *place;
     int i=0;
     
     char token[50];
     if(str)
     {
         for(i=0; str[i]!=delim[0]; i++)
           {
                   token[i]=str[i];      
                   place++;
           }            
     } 
//     else if(!str)
//     {
//            for(i=0; place[i]!=NULL; i++)
//            {
//                    token[i]=place[i];
//            }
//            *place=(*place+i);
//     }
     cout << token;   
     return token;  
}
The function definition is invalid. You are returning pointer to the first element of a local array that will be destroyed after exiting the function.
Okay, after another revision, I have been able to tokenize the string up until the first delimiter. After that, if I put NULL in the first parameter, the program fails.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <iostream>
using namespace std;
char *mystrtok(char *str, const char *delim);
int main()
{
    char * end;
    char str[] = "Here is a string";
        cout << str << endl;
        end=mystrtok(str, " ");
        while(end!=NULL)
        {
            cout << end;
            end=mystrtok(NULL, " ");
        }
        return 0;
}


char *mystrtok(char *str, const char *delim)
{
     static char *place;
     int i=0;
     char *token;
     
     if(*str)
     {
         while(*str==*delim)
             str++;
         for(i=0;*str!=*delim; i++)
         {
                token[i]=*str; 
                str++;
         }
     }
     if(str==NULL)
     {
         str=place;
         while(*str==*delim)
            str++;
         if(*str)
         {
            for(i=0;*str!=*delim; i++)
            {
                   token[i]=*str; 
                   str++;
                   if(!*str)
                        return token;
            }
         }
         else if(!*str)
             return NULL;
     }
     return token;  
}
You are using dangling pointers. I just got here, so I haven't had a chance to examine your algorithm yet.... but have you had a chance to check out the FAQ on strtok()? It might help you a bit.
http://www.cplusplus.com/faq/sequences/strings/strtok/

I'll post back in a few after I look at your code.
OK, here I am.

First, make sure to click on the link I gave you, and also read the link about Pointers and C-Strings. You are trying to do this:

1
2
char* foo;  // Foo is a pointer to char, but it points to some random piece of memory.
foo[n] = 'H';  // NO! This will cause a crash! 

You had it right the first time:
1
2
char foo[50];
foo[n] = 'H';  // Yay! So long as n is in 0..49 you are good to go! 


Remember also that *str is the same as str[0]. If you want to check to see that str points to something, you must check whether its value is non-zero (or not NULL), not whether what it points to is non-zero. So, the correct test is:

if (str != NULL) or, more succinctly, if (str)


Now, on to the function of the algorithm. The strtok() algorithm doesn't actually copy anything, so your function shouldn't either. Remember, if you read the link I gave you, remember that strtok() cheats -- it just sticks null characters ('\0') in the string and returns a pointer to the string you passed it! Hence, you don't need the token variable. (Or the i variable either, for that matter, but we'll get to that in a second.)


Next, the idea of your place variable is a good one. (It is what I called "start" in the link I gave you.)

However, remember that you must either give it a value, or take a value from it. You cannot do neither. Also, you must give it a value before you take one. It is OK to do both.

To decide which, you must consider how strtok() is called. We'll take it backwards because it is easier to consider this way:

... = strtok( NULL, ... );
The argument str is NULL, so we must use the saved place.

strtok( mystr, ... )
The argument str is not NULL, so we do not need any saved place. Before the function returns, make sure to set place to the next place to use for str if the function is called again with NULL as the argument to str.


Avoid duplicating code. Right now, you have two branches (two ifs): one for if str is not NULL, and one for if it is. The only time the function behaves differently is if str is initially NULL; the rest of the function does the same thing either way.


Read through the links I gave you, and try again, and post back.

Good luck!
Topic archived. No new replies allowed.