1、strtok() 函数的作用
strtok()
是 C 标准库中的字符串分割函数,功能是将字符串按照指定的分隔符切割成一个个“token(子串)”。函数原型(在 中)。
char *strtok(char *str, const char *delim);
str
首次调用时传入要分割的字符串,后续传入 NULL
继续分割。
delim
分隔符字符串(可包含多个字符,如 ",. "
)
2、工作原理(核心机制)
第一次调用,strtok(str, delim)
修改 str
,将第一个 token
末尾的分隔符 '\0'
替换(直接破坏原字符串)。
返回第一个 token
。后续调用,strtok(NULL, delim)
从上次位置继续,返回下一个 token
。没有更多 token
后,返回 NULL
。
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "Hello,World,This,is,C";
char *token = strtok(str, ",");
while (token != NULL) {
printf("%s\n", token);
token = strtok(NULL, ","); // 继续提取下一个
}
return 0;
}
注意:
strtok()
会在分隔符位置写入 '\0'
,原字符串会被修改。所以不能多线程安全,多线程用 strtok_r()
。只有第一次传字符串地址,后续传 NULL
。不能在同一线程里同时嵌套使用多个 strtok()
,因为共用内部状态。
3、strtok_r()(线程安全版本)
strtok_r()
是 strtok()
的线程安全版本,用于在 C 语言中按指定分隔符分割字符串。它避免了 strtok()
使用全局静态指针的问题,可以多个线程或多个字符串同时安全地进行分割操作。
char *strtok_r(char *str, const char *delim, char **saveptr);
saveptr
用于保存分割状态,适合多线程或递归中安全使用。
#include <stdio.h>
int main() {
char str[] = "Hello,World,This,is,C";
char *saveptr;
char *token = strtok_r(str, ",", &saveptr);
while (token != NULL) {
printf("%s\n", token);
token = strtok_r(NULL, ",", &saveptr);
}
return 0;
}
4、使用场景
strtok()
函数常用于字符串分割,可以于解析CSV数据,命令行参数解析,配置文件读取,URL、路径、版本号拆分,网络协议数据解析(如HTTP头)等。
1)处理CSV格式数据
#include <stdio.h>
int main() {
char str[] = "apple,banana,orange";
char *token = strtok(str, ",");
while (token != NULL) {
printf("%s\n", token);
token = strtok(NULL, ",");
}
return 0;
}
2)命令行输入解析
#include <stdio.h>
int main() {
char input[] = "copy file1.txt file2.txt";
char *token = strtok(input, " ");
while (token != NULL) {
printf("Token: %s\n", token);
token = strtok(NULL, " ");
}
return 0;
}
3)解析配置文件
#include <stdio.h>
int main() {
char line[] = "key1=value1";
char *key = strtok(line, "=");
char *value = strtok(NULL, "=");
printf("key=%s, value=%s\n", key, value);
return 0;
}
4)处理URL、路径或版本号等结构
#include <stdio.h>
int main() {
char url[] = "http://www.example.com/index.html";
char *token = strtok(url, "/");
while (token != NULL) {
printf("%s\n", token);
token = strtok(NULL, "/");
}
return 0;
}