嵌套使用strtok_r时子令牌混入父分隔符的技术问题排查
问题解决:嵌套strtok_r出现父分隔符的原因及修复
嘿,我一眼就揪出问题根源了——你父循环里的strtok_r调用用错了分隔符!
问题核心
看你父循环的最后一行代码:
tok = strtok_r(NULL, "\n", &endStr);
这里你错误地把分隔符换成了"\n",但实际上应该继续用最初定义的delim(也就是";")来拆分剩余字符串。这就导致第二次循环时,strtok_r完全忽略了剩余内容里的;分隔符,直接把city2,243;city3,500;city4,50里的后半段当成了一个完整token传给子循环,子循环用","拆分时自然就出现了243;city3这种混杂父分隔符的内容。
修复步骤
修正父循环的分隔符
把父循环里的"\n"改回delim,让strtok_r继续用;拆分剩余字符串:tok = strtok_r(NULL, delim, &endStr);修复其他潜在bug
还有几个小问题会导致程序不稳定,一起修正:- 分配
buf时,要给字符串结束符\0留位置,应该写成malloc(strlen(str)+1),否则strcpy会越界 - 使用
INT_MAX需要包含头文件<limits.h>,否则可能出现未定义行为 - 分配
minCity时,不能用sizeof(loc[j]->name)(这只会得到指针的大小),应该用strlen(loc[j]->name)+1来匹配字符串的实际长度 - 别忘了释放每个
loc节点的内存,避免内存泄漏
- 分配
修正后的完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <limits.h> // 新增:用于INT_MAX #define MAX_CITIES 120 typedef struct { char *name; int distance; } location_s; int main(void) { char *str = "city1,1223;city2,243;city3,500;city4,50"; char *delim = ";"; char *subDelim = ","; char *endStr; char *tok, *buf; location_s *loc[MAX_CITIES]; // 修复:分配strlen(str)+1的空间,容纳结束符 buf = malloc(strlen(str)+1); strcpy(buf, str); tok = strtok_r(buf, delim, &endStr); int tokenCount = 0, subTokenCount = 0; while (tok) { char *lastToken; char *sTok = strtok_r(tok, subDelim, &lastToken); loc[tokenCount] = (location_s*)malloc(sizeof(location_s)); while(sTok){ printf("now sTok=%s\n",sTok); if(subTokenCount == 0) loc[tokenCount]->name = sTok; if(subTokenCount == 1) loc[tokenCount]->distance = atoi(sTok); subTokenCount++; sTok = strtok_r(NULL, subDelim, &lastToken); } subTokenCount = 0; tokenCount++; // 修复:用正确的分隔符delim继续拆分 tok = strtok_r(NULL, delim, &endStr); } /* Iterating through list of location */ int minDistance = INT_MAX; int refPoint = 0, j = 0; char *minCity; for(int i=0; i < tokenCount; i++) { if (loc[i]->distance < minDistance) { minDistance = loc[i]->distance; j = i; } } // 修复:按字符串实际长度分配空间 minCity = malloc(strlen(loc[j]->name)+1); strcpy(minCity, loc[j]->name); printf("min: %d", minDistance); printf("\nplace: %s", minCity); // 新增:释放每个loc节点的内存 for(int i=0; i<tokenCount; i++){ free(loc[i]); } free(minCity); free(buf); return 0; }
运行结果
修正后运行会得到正确的输出:
now sTok=city1 now sTok=1223 now sTok=city2 now sTok=243 now sTok=city3 now sTok=500 now sTok=city4 now sTok=50 min: 50 place: city4
内容的提问来源于stack exchange,提问作者Julito Sanchis
相关产品推荐
相关产品推荐

