C语言strtok分词中如何获取当前处理token的前一个token
C语言分词时获取前一个相邻Token的实现
核心实现思路
不需要维护复杂的全量历史分词计数器:只有当需要保留N步之前的多段分词结果时,才需要用固定大小的环形数组做存储。当前需求仅需获取当前token的紧邻前序结果,仅需单独维护一个prev_word指针,每轮遍历更新即可:
- 初始化
prev_word为NULL,代表当前还没有处理过任何分词 - 每当取出一个当前分词
word时,prev_word中存的就是刚好和当前token相邻的上一个分词 - 当前token的业务逻辑处理完成后,将当前
word赋值给prev_word,再去取下一个分词,保证下一轮循环时的相邻关系正确
原代码的待补全问题
- 未校验命令行参数数量,直接读取
argv[2]会触发非法内存访问 - 未判断
fopen的返回值,文件不存在/无权限时会直接操作空指针崩溃 - 未保存历史分词指针,遇到
(时无法获取其前面的相邻分词 - 逻辑冗余:进入分词循环时已经保证
word != NULL,if判断里重复的空值判断没有意义 - 代码未闭合:缺少循环收尾、文件关闭的逻辑,直接编译会报语法错误
可运行的修改后代码
#include <stdio.h> #include <string.h> int main(int argc, char **argv) { // 增加参数合法性校验 if (argc < 3) { printf("使用方式: %s 输入文件路径\n", argv[0]); return 1; } char line[1000]; char *delimeters = ".,; \t\n"; FILE *input = fopen(argv[2], "r"); // 增加文件打开状态校验 if (input == NULL) { perror("打开输入文件失败"); return 1; } // 跨整文件分词场景:prev_word 定义在循环外;如果按行独立分词则定义在循环内 // char *prev_word = NULL; while (fgets(line, 1000, input) != NULL) { char *prev_word = NULL; // 按行独立分词,每一行重置前序指针 char *word = strtok(line, delimeters); while (word != NULL) { // 当前处理到的token是(时,prev_word就是它前面紧邻的分词 if (strcmp(word, "(") == 0) { printf("Enters IF 3\n"); // 边界判断:如果行首就是(,prev_word为NULL,避免空指针访问 if (prev_word != NULL) { printf("括号前的相邻分词: %s\n", prev_word); } // 原有逻辑:取括号后面的token作为方法名 char *method_name = strtok(NULL, delimeters); if (method_name != NULL) { printf("Method %s\n", method_name); } } // 更新前序指针,供下一个token使用 prev_word = word; // 取下一个分词 word = strtok(NULL, delimeters); } } fclose(input); return 0; }
关键注意事项
strtok返回的指针直接指向栈上的line数组内存,只要当前行的分词流程没有结束,prev_word指向的字符串内容不会失效,不需要额外申请内存拷贝内容- 如果你的分词规则是跨换行连续处理(即换行不打断分词的相邻关系),只需要把
prev_word的定义移动到外层逐行读取的循环外面,不要每读一行就重置为NULL - 做边界判断:如果某行的第一个token就是匹配的
(,此时prev_word为NULL,一定要做空值判断,避免空指针读写导致程序崩溃
内容的提问来源于stack exchange,提问作者AxelCagira
相关产品推荐
相关产品推荐

