我国档案网站建设来客seo
strtok 是 C 标准库中的字符串分割函数,用于将一个字符串拆分成多个部分(token),以某些字符(称为分隔符)为界限。
函数原型
char *strtok(char *str, const char *delim);
 
-  
参数:
str:待分割的字符串。如果是第一次调用,传入要分割的字符串;之后的调用需传入NULL,以继续上一次的分割。delim:字符串,包含所有分隔符的字符集合。例如," "(空格)或"/"(斜杠)。
 -  
返回值:
- 返回指向字符串中 当前部分 的指针。
 - 如果没有更多部分可返回,返回 
NULL。 
 
用法规则
- 初次调用时,传入字符串 
str,函数会从str中找到第一个部分。 - 函数会用 
'\0'替换找到的分隔符(破坏原字符串)。 - 后续调用时,传入 
NULL,函数会继续从上次结束的位置查找下一部分。 - 不能在多线程环境中使用,因为 
strtok使用的是静态变量保存状态。 
示例
#include <stdio.h>
#include <string.h>int main() {char str[] = "C programming is fun";const char *delim = " "; // 用空格作为分隔符char *token;// 初次调用 strtoktoken = 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 <stdio.h>
#include <string.h>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 <stdio.h>
#include <string.h>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 <stdio.h>
#include <string.h>int main() {char str[] = "C,programming,is,fun";const char *delim = ",";char *token;// 初次调用 strtoktoken = strtok(str, delim);printf("First token: %s\n", token); // 输出 "C"// 后续调用 strtoktoken = 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。 
 - 静态指针更新为 
 
静态指针的局限性
1. 线程不安全
strtok 的静态指针是全局共享的,多个线程同时调用 strtok 会导致状态混乱。
解决方案:使用线程安全的 strtok_r 函数,它将状态保存到用户提供的指针(而非静态变量)中。
2. 不能同时分割多个字符串
因为 strtok 的静态指针只能记录一个字符串的分割状态。如果需要同时分割多个字符串,应使用其他方法(如 strtok_r 或自定义逻辑)。
总结
strtok用于字符串分割,但会修改原字符串,并且线程不安全。- 多线程环境下,推荐使用 
strtok_r。 - 分割的字符串存储在原字符串中,指针返回的是分割后的部分,原字符串会被破坏。
 
