尝试理解strtok实现中的代码

4

我是一名IT技术新手,目前正在通过跟随斯坦福大学的CS107视频学习(我不是那里的学生)。

如果有人感兴趣,下面是链接。

看到下面这个strtok的实现,我不确定为什么第一个if语句要这样写: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;
}

以下是我迄今为止发现的内容:

1)静态的p是一个局部静态变量,一旦找到一个令牌,它就会持续存在,并在找不到令牌时重置为NULL

2)随后调用strtokens作为NULL传递

因此,如果第一个检查写成以下形式,它不会有任何区别:
if (s == NULL && p == NULL)

或者说它以这种方式编写的原因是什么?

最后: return p = NULL; 这只是以下简写吗:

p = NULL;
return p;

CS107 Winter 18 Screencasts

2011年的惊人CS107讲座

基于Rpi的CS107e


1
如果你正在学习 C 语言,尽量不要在 if 条件语句中编写代码。 - tadman
我同意,我有很好的Python经验,但在Python中我并没有看到或使用过那个东西 - 这就是为什么当我第一次阅读这个实现时感到害怕的原因。 - Sam Hammamy
1
这是一些非常丑陋的代码,即使按照C标准来看也是如此,因此编写这段代码的作者肯定不是为了清晰易懂而努力。 - tadman
2个回答

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

并不完全相同

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

尽管它们产生相同的结果,但当spNULL时,您已经正确地确定了后续调用strtok必须使用NULL进行传递,但是如果仍有要返回的标记,则p不会测试NULL。因此,((s = p) == NULL)是一个巧妙的技巧,将s指向可能找到更多标记的字符串的其余部分。在C中,当您评估像A && B这样的表达式时,A被评估并且只有在A被评估为真时才评估B,原因是sequent points。如果s不是NULL,则永远不会评估((s = p) == NULL),也不会分配s = p
如果sNULL,则会评估((s = p) == NULL)。首先评估s = p,这是一种赋值操作。如果p不是NULL,则s指向p指向的位置(源代码的其余部分),并且与NULL进行比较时,它将被评估为false,因此return NULL不会执行,函数继续寻找标记。
然而,如果p也是NULL,则s被设置为指向NULL,并且与NULL进行比较时,它将被评估为true,整个if将被评估为true,并执行return NULL。当s最初为NULLpNULL时,这意味着已经找到所有标记并返回,因此该函数应返回NULL。它可以重写为:
if(s == NULL)
{
    if(p == NULL)
        return NULL;

    s = p;
}
...

请注意,指派的值是指派本身的值。
return a = b;

与做

相同。
a = b;
return b;

太棒了!这是我现在的代码: 在第一次调用s += strspn(s, sep);时:如果找到了sep,则指针s将移动1个位置。然后,p = s + strcspn(s, sep);将在s中设置p为分隔符之后的位置。 因此,在第二次调用中,p不为空。但是在第二次调用中,s被设置为上一次调用中设置的p。因此,s += strspn(s, sep);实际上是p += strspn(p, sep);,因为正如你所说,当sNULL时,在第二次调用中发生s=p - Sam Hammamy

1
因此,如果将其写成以下形式,第一个检查是否相同:
if (s == NULL && p == NULL)

p 为 NULL 时,是的。当 p 不为 NULL 时,不是。因为此时 s=p 的副作用不会发生。并且当 if 语句为 false 时,后面会使用该值 s
最后:return p = NULL; 只是以下缩写吗:
p = NULL;
return p;

是的。

这是一个很好的回答,但上面的解释非常出色! - Sam Hammamy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接