找到所需序列发生的点非常容易:strstr支持:
char str[] = "this is abc a big abc input string abc to split up";
char *pos = strstr(str, "abc");
Run Code Online (Sandbox Code Playgroud)
因此,此时,pos指向abc较大字符串中的第一个位置。这就是事情变得有点难看的地方。strtok有一个讨厌的设计,它 1) 修改原始字符串,以及 2) 在内部存储一个指向字符串中“当前”位置的指针。
如果我们不介意做大致相同的事情,我们可以这样做:
char *multi_tok(char *input, char *delimiter) {
static char *string;
if (input != NULL)
string = input;
if (string == NULL)
return string;
char *end = strstr(string, delimiter);
if (end == NULL) {
char *temp = string;
string = NULL;
return temp;
}
char *temp = string;
*end = '\0';
string = end + strlen(delimiter);
return temp;
}
Run Code Online (Sandbox Code Playgroud)
这确实有效。例如:
int main() {
char input [] = "this is abc a big abc input string abc to split up";
char *token = multi_tok(input, "abc");
while (token != NULL) {
printf("%s\n", token);
token = multi_tok(NULL, "abc");
}
}
Run Code Online (Sandbox Code Playgroud)
产生大致预期的输出:
this is
a big
input string
to split up
Run Code Online (Sandbox Code Playgroud)
尽管如此,它很笨拙,难以使线程安全(您必须使其内部string变量线程局部)并且通常只是一个蹩脚的设计。使用(例如)类似的接口strtok_r,我们至少可以解决线程安全问题:
typedef char *multi_tok_t;
char *multi_tok(char *input, multi_tok_t *string, char *delimiter) {
if (input != NULL)
*string = input;
if (*string == NULL)
return *string;
char *end = strstr(*string, delimiter);
if (end == NULL) {
char *temp = *string;
*string = NULL;
return temp;
}
char *temp = *string;
*end = '\0';
*string = end + strlen(delimiter);
return temp;
}
multi_tok_t init() { return NULL; }
int main() {
multi_tok_t s=init();
char input [] = "this is abc a big abc input string abc to split up";
char *token = multi_tok(input, &s, "abc");
while (token != NULL) {
printf("%s\n", token);
token = multi_tok(NULL, &s, "abc");
}
}
Run Code Online (Sandbox Code Playgroud)
不过,我想我现在暂时搁置它——为了获得一个真正干净的界面,我们真的想重新发明一些像协程这样的东西,在这里发布可能有点多。