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

C语言如何解决从括号中提取单词存入结构体的strtok异常问题

问题原因

问题核心是strtok函数不可重入:strtok内部使用静态全局变量存储上一次拆分的位置上下文,同一进程内所有strtok调用共享这个上下文:

  • 主函数第一次调用strtok(row, "(")后,内部静态变量记录了当前的拆分位置
  • get_and_print_word函数中调用的strtok(r, " ")直接覆盖了strtok内部存储的主函数拆分上下文
  • 回到主函数执行pch = strtok(NULL, "(")时,使用的是被覆盖的异常上下文,自然会返回错误的指针地址

解决方案

方案1:使用可重入拆分函数strtok_r(推荐)

strtok_r是POSIX标准提供的strtok线程安全/可重入版本,要求用户自行传入指针存储当前拆分的上下文,不同拆分流程的上下文完全独立不会互相干扰。
如果是Windows平台可以替换为strtok_s,参数逻辑完全一致。

修改后主函数代码:

int main(int argc, char * argv[]) {
  char row[] = "(octopus kitten) (game cake) (soccer football)";
  char *pch, *main_ctx; // 单独存储主函数拆分流程的上下文
  pch = strtok_r(row, "(", &main_ctx);

  while (pch != NULL) {
    pch[strcspn(pch, ")")] = '\0';
    get_and_print_word(pch);
    pch = strtok_r(NULL, "(", &main_ctx);
  }

  return 0;
}

修改后get_and_print_word函数代码:

void get_and_print_word(char str[]) {
  char r[4000];
  strcpy(r, str);
  char *c, *sub_ctx; // 单独存储子拆分流程的上下文
  c = strtok_r(r, " ", &sub_ctx);
  for (int i = 0; i < 2; i++) {
    printf("%s\n", c);
    c = strtok_r(NULL, " ", &sub_ctx);
  }
}

方案2:先全量提取括号片段再统一处理

如果环境不支持strtok_r类的可重入拆分函数,可以先把所有括号内的字符串提取出来存入数组,全量提取完成后再遍历数组拆分每个片段的单词,避免两个strtok流程同时运行互相干扰。

int main(int argc, char * argv[]) {
  char row[] = "(octopus kitten) (game cake) (soccer football)";
  char *pch;
  // 存储提取到的括号片段,可根据实际场景调整容量
  char segments[10][100] = {0};
  int seg_count = 0;

  // 第一步:仅提取所有括号内的片段存入数组
  pch = strtok(row, "(");
  while (pch != NULL && seg_count < 10) {
    pch[strcspn(pch, ")")] = '\0';
    strcpy(segments[seg_count++], pch);
    pch = strtok(NULL, "(");
  }

  // 第二步:统一处理每个片段拆分单词
  for (int i = 0; i < seg_count; i++) {
    get_and_print_word(segments[i]);
  }

  return 0;
}

内容的提问来源于stack exchange,提问作者MichaelLearner

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 19:36:01