You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

嵌套使用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这种混杂父分隔符的内容。

修复步骤

  1. 修正父循环的分隔符
    把父循环里的"\n"改回delim,让strtok_r继续用;拆分剩余字符串:

    tok = strtok_r(NULL, delim, &endStr);
    
  2. 修复其他潜在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 09:06:17