Sam Hammamy
Sam Hammamy

Reputation: 11017

Trying to understand the code in this implementation of strtok

I am very much a c newbie and I am learning by following CS107 videos from Standford (I am not a Student there).

Links are below if anyone is interested

Looking at the below implementation of strtok, I am not sure why the first if statement is written this way: if (s == NULL && ((s = p) == NULL))

char *strtok(char *s, const char *sep)
{
    static char *p = NULL;

    if (s == NULL && ((s = p) == NULL))
        return NULL;
    s += strspn(s, sep);
    if (!*s)
        return p = NULL;
    p = s + strcspn(s, sep);
    if (*p)
        *p++ = '\0';
    else 
        p = NULL;
    return s;
}

Here's what I have identified so far:

1) the static p is a local static so that it persists once a token is found, and reset to NULL when no more are found

2) subsequent calls of strtoken pass in s as NULL

Therefore wouldn't the first check be the same if it were written as:

if (s == NULL && p == NULL)

Or is there a reason it is written the way it is?

Finally: return p = NULL; is this just a shorthand for:

p = NULL;
return p;

CS107 Winter 18 Screencasts

Amazing CS107 Lectures from 2011

An Rpi based CS107e

Upvotes: 4

Views: 895

Answers (2)

Pablo
Pablo

Reputation: 13580

if (s == NULL && ((s = p) == NULL))

is not really the same as

if (s == NULL && p == NULL)

although they have the same result, when s and p are NULL.

You've identified correctly that subsequent calls of strtok must be passed with NULL, however if the are still tokens to be returned, p is not going to test for NULL.

So the ((s = p) == NULL) is a clever trick to assign s to point to the rest of the string where more token might be found.

In C when you evaluate an expression like A && B, A gets evaluated and B gets only evaluated if and only if A was evaluated as true, the reason for this are sequent points.

If s is not NULL, then ((s = p) == NULL) is never evaluated, s = p is never assigned.

If s is NULL, then ((s = p) == NULL) gets evaluated. First s = p is evaluated and this is an assignment. If p is not NULL, then s points to where p is pointing (the rest of the source) and when compared to NULL, it is evaluated to false, thus the return NULL is not executed and the function continues looking for tokens.

If however p is also NULL, s is set to point to NULL and when compared to NULL it evaluates to true, the whole if evaluates to true and return NULL is executed. When s initially is NULL and p is NULL, then that means that all token have been found and return, so the function should return NULL. It can be rewritten as:

if(s == NULL)
{
    if(p == NULL)
        return NULL;

    s = p;
}
...

Note that the value of an assignment is the value of the assigment itself.

return a = b;

is the same as doing

a = b;
return b;

Upvotes: 4

MFisherKDX
MFisherKDX

Reputation: 2866

Therefore wouldn't the first check be the same if it were written as:

if (s == NULL && p == NULL)

When p is NULL, yes. When p is not NULL, no. Because then the side effect of s=p doesn't happen. And this value s is used later when the if statement is false.

Finally: return p = NULL; is this just a shorthand for:

p = NULL;
return p;

Yes.

Upvotes: 1

Related Questions