strtok
是 C 标准库中的字符串分割函数,用于将一个字符串拆分成多个部分(token),以某些字符(称为分隔符)为界限。
char *strtok(char *str, const char *delim);
参数:
str
:待分割的字符串。如果是第一次调用,传入要分割的字符串;之后的调用需传入 NULL
,以继续上一次的分割。delim
:字符串,包含所有分隔符的字符集合。例如," "
(空格)或 "/"(斜杠)
。返回值:
NULL
。str
,函数会从 str
中找到第一个部分。'\0'
替换找到的分隔符(破坏原字符串)。NULL
,函数会继续从上次结束的位置查找下一部分。strtok
使用的是静态变量保存状态。#include
#include
int main() {
char str[] = "C programming is fun";
const char *delim = " "; // 用空格作为分隔符
char *token;
// 初次调用 strtok
token = strtok(str, delim);
while (token != NULL) {
printf("%s\n", token); // 打印分割的每一部分
token = strtok(NULL, delim); // 后续调用
}
return 0;
}
输出:
C
programming
is
fun
原字符串被修改:strtok
会在分隔符处插入 '\0'
,因此原字符串内容会被破坏。如果需要保留原字符串,请先复制到一个新字符串再操作。
不能并发使用:由于 strtok
使用内部静态变量保存状态,它在多线程程序中不安全。多线程环境下,请使用 strtok_r
。
分隔符 delim
可以包含多个字符,strtok
会将所有出现在 delim
中的字符视为分隔符。例如:
#include
#include
int main() {
char str[] = "apple;orange,banana|grape";
const char *delim = ";,|"; // 多个分隔符
char *token;
token = strtok(str, delim);
while (token != NULL) {
printf("%s\n", token);
token = strtok(NULL, delim);
}
return 0;
}
输出:
apple
orange
banana
grape
在多线程环境下,使用 strtok_r
(线程安全版本)。函数原型如下:
char *strtok_r(char *str, const char *delim, char **saveptr);
str
:首次调用传入要分割的字符串,后续调用传入 NULL
。delim
:分隔符集合。saveptr
:保存分割状态的指针变量,需由调用者提供。#include
#include
int main() {
char str[] = "apple;orange,banana|grape";
const char *delim = ";,|";
char *token;
char *saveptr; // 保存状态
token = strtok_r(str, delim, &saveptr);
while (token != NULL) {
printf("%s\n", token);
token = strtok_r(NULL, delim, &saveptr);
}
return 0;
}
输出:
apple
orange
banana
grape
NULL
?strtok
函数内部使用了一个 静态指针 来记录分割状态。这个静态指针会指向原字符串中上一次分割结束的位置。在首次调用时,strtok
初始化这个指针为传入的字符串地址。在后续调用时,通过传入 NULL
,strtok
会继续从这个内部静态指针的位置接着分割。
初次调用:
token = strtok(str, delim);
str
是待分割字符串。strtok
将分隔符替换为 '\0'
,并返回找到的第一个分割部分,同时保存分割结束的位置到静态指针中。后续调用:
token = strtok(NULL, delim);
NULL
告诉 strtok
使用保存的静态指针,从上次分割结束的位置继续分割。strtok
会更新静态指针的位置。#include
#include
int main() {
char str[] = "C,programming,is,fun";
const char *delim = ",";
char *token;
// 初次调用 strtok
token = strtok(str, delim);
printf("First token: %s\n", token); // 输出 "C"
// 后续调用 strtok
token = strtok(NULL, delim);
printf("Second token: %s\n", token); // 输出 "programming"
token = strtok(NULL, delim);
printf("Third token: %s\n", token); // 输出 "is"
token = strtok(NULL, delim);
printf("Fourth token: %s\n", token); // 输出 "fun"
token = strtok(NULL, delim);
printf("Final token: %s\n", token); // 输出 "(null)",分割完成
return 0;
}
输出:
First token: C
Second token: programming
Third token: is
Fourth token: fun
Final token: (null)
内部指针变化:
str
是 "C,programming,is,fun"
。"programming,is,fun"
。"is,fun"
。"fun"
。NULL
。strtok
的静态指针是全局共享的,多个线程同时调用 strtok
会导致状态混乱。
解决方案:使用线程安全的 strtok_r
函数,它将状态保存到用户提供的指针(而非静态变量)中。
因为 strtok
的静态指针只能记录一个字符串的分割状态。如果需要同时分割多个字符串,应使用其他方法(如 strtok_r
或自定义逻辑)。
strtok
用于字符串分割,但会修改原字符串,并且线程不安全。strtok_r
。