安全地跳过 strtok 的空终止符

skip strtok's null terminators safely

我想使用 strtok 然后 return 字符串 strtok 放置的空终止符之后。

char *foo(char *bar)
{
strtok(bar, " ");
return after_strtok_null(bar);
}
/*
examples:
foo("hello world") = "world"
foo("remove only the first") = "only the first"
*/

我的代码 不是 用于跳过第一个单词(我知道一个简单的 while 循环就可以)但我确实想使用 strtok一次 return 未标记化的部分。

我会在问题的最后提供我想做的事情的细节,虽然我认为这真的没有必要

我想到的一个解决方案是简单地跳过所有空终止符,直到我到达一个非空终止符:

char *foo(char *bar)
{
bar = strtok(bar, " ");
while(!(*(bar++)));
return bar;
}

这适用于上面显示的示例,但是当涉及到在单个单词上使用它时 - 我可能会错误地将字符串的空终止符识别为 strtok 的空终止符,然后我可能会访问非- 分配的内存。

例如,如果我尝试 foo("demo"\* '[=17=]' *\)strtok"demo"\* '[=19=]' *\ 然后,如果我要 运行 while 循环,我将调用字符串 demo 之后的部分。我尝试过的另一种解决方案是使用 strlen,但这个解决方案存在完全相同的问题。

我正在尝试创建一个获取句子的函数。有些句子的第一个词以冒号结尾,但不一定。如果第一个单词以冒号结尾,则该函数需要获取第一个单词并将其(不带冒号)插入到某个全局 table 中。然后 return 没有第一个冒号的句子 - 终止单词并且如果单词有冒号则单词后面没有空格 - 在开头终止单词,否则,只是 return 没有空格的句子句子的开头。

您可以使用 str[c]spn 代替:

char *foo(char *bar) {
    size_t pos = strcspn(bar, " ");
    pos = strspn((bar += pos), "");
    // *bar = '[=10=]';   // uncomment to mimic strtok
    return bar + pos;
}

您将得到空字符串的预期子字符串。

一个好处是您可以避免更改原始字符串 - 即使模仿 strtok 是微不足道的...