目录
[strtok_r(POSIX 标准)](#strtok_r(POSIX 标准))
[strtok_s(C11 标准)](#strtok_s(C11 标准))
介绍
strtok 是 C 标准库(<string.h>)中用于分割字符串的函数。它将一个字符串按指定的分隔符拆分成多个子字符串(标记)。
函数原型
cpp
char *strtok(char *str, const char *delim);
-
str
: 待分割的字符串(首次调用传入);后续调用需传入NULL
(表示继续分割同一字符串)。 -
delim
: 包含分隔符的字符串(每个字符都认为是分隔符)。 -
返回值:返回下一个标记的指针;无更多标记时返回
NULL
。
工作原理
- 第一次调用时,函数会查找字符串str中第一个不在delim中的字符(即标记的开始)。
- 然后从该位置开始,继续查找在delim中的字符(即标记的结束位置),并将其替换为'\0'(字符串结束符),这样就得到了一个标记。
- 函数返回指向该标记的指针。
- 后续调用时,第一个参数传入NULL,函数会从上一次保存的位置继续查找下一个标记。
核心特性
修改原字符串
strtok 会直接修改原始字符串,将分隔符替换为 '\0'。若需保留原字符串,应先拷贝。
连续分隔符被忽略
如果字符串中有连续的分隔符,strtok会跳过它们,即不会返回空字符串。
不可重入/非线程安全
函数内部使用静态变量记录位置。多线程中应用 strtok_r
(POSIX)或 strtok_s
(C11)。
字符串结束
当没有更多标记时,函数返回NULL。
使用步骤
-
首次调用:传入目标字符串和分隔符。
-
后续调用 :传入
NULL
和分隔符(继续分割同一字符串)。 -
结束条件 :返回
NULL
时表示无更多标记。
cpp
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "apple,banana,,cherry;date";
char *token = strtok(str, ",;"); // 第一次调用,传入字符串 分隔符为逗号或分号
while (token != NULL) {
printf("Token: %s\n", token);
token = strtok(NULL, ",;"); // 继续分割 后续调用传入NULL
}
return 0;
}
// 输出 注意:连续的分隔符 ,, 被忽略,未产生空标记。
// Token: apple
// Token: banana
// Token: cherry
// Token: date
线程安全替代方案
strtok_r
(POSIX 标准)
cpp
char *strtok_r(char *str, const char *delim, char **saveptr);
cpp
// saveptr:用户提供的指针,用于保存分割状态
char *saveptr;
token = strtok_r(str, ",;", &saveptr);
while (token) {
// 处理 token
token = strtok_r(NULL, ",;", &saveptr);
}
strtok_s
(C11 标准)
cpp
char *strtok_s(char *str, const char *delim, char **context);
cpp
// context:类似 saveptr 的上下文指针。
char *context = NULL;
token = strtok_s(str, ",;", &context);
// 使用方式同 strtok_r
注意事项
空字符串处理
若字符串全部分隔符或无有效内容,首次调用即返回 NULL。
cpp
char s[] = ";;;";
char *t = strtok(s, ";"); // t = NULL
不可嵌套调用
同一线程内不可嵌套使用 strtok
(因共享静态状态)。
分隔符为单字符
如果delim
是字符串(如 ";,"
),则字符串里的每个字符(;
或 ,
)都是独立分隔符。
总结表格
特性 | 说明 |
---|---|
是否修改原字符串 | 是(分隔符替换为 \0 ) |
连续分隔符 | 被忽略 |
线程安全 | 否(用 strtok_r /strtok_s 替代) |
首次调用参数 | 传入目标字符串指针 |
后续调用参数 | 传入 NULL |
结束条件 | 返回 NULL |
掌握 strtok
的关键是理解其修改原字符串 和静态状态记录的特性,合理使用时注意线程安全和字符串备份!