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; }