原指针在内容复制到另一数组后受影响的问题及修复方法咨询
嘿,这个问题我太熟了!大概率是strtok这个“坑货”搞的鬼,我来给你拆解下原因,再给你几个实用的修复方案。
首先说问题出在哪:你应该是在is_ingredient_list和is_ingredient两个函数里都用了strtok来做分词吧?strtok内部用了一个静态变量来记住上次分词的位置,相当于它是全局共享的状态。当你在is_ingredient里调用strtok处理临时数组时,它会直接覆盖这个静态变量的内容,等你回到is_ingredient_list继续用strtok时,它早就忘了之前的位置,自然只能停在第一个token了,看起来就像是原指针被影响了一样。
那怎么修复呢?给你两个靠谱的办法:
用可重入的分词函数替代
strtok
如果你是在POSIX系统(比如Linux、macOS)上开发,用strtok_r;如果是Windows系统,用strtok_s。这两个函数需要你自己传一个指针来保存分词的位置,每个函数用自己的位置变量,就不会互相干扰了。比如你的
is_ingredient_list可以改成这样:void is_ingredient_list(char* original_str) { char delim[] = " "; // 这里换成你实际用的分隔符 char* save_ptr_list; // 专门用于list函数的位置指针 char* token = strtok_r(original_str, delim, &save_ptr_list); while (token != NULL) { is_ingredient(token); token = strtok_r(NULL, delim, &save_ptr_list); } }然后
is_ingredient里处理临时数组时,也用自己的位置变量:int is_ingredient(const char* str){ char tmp[1024]; strncpy(tmp, str, sizeof(tmp)); tmp[sizeof(tmp)-1] = '\0'; char delim[] = " "; // 你的分隔符 char* save_ptr_ingred; // 专门用于当前函数的位置指针 char* tmp_token = strtok_r(tmp, delim, &save_ptr_ingred); while (tmp_token != NULL) { // 这里写你处理每个token的逻辑 tmp_token = strtok_r(NULL, delim, &save_ptr_ingred); } return 1; // 换成你实际的返回值 }手动实现分词逻辑,完全绕开
strtok
如果你不想依赖系统特定的函数,也可以自己写分词逻辑,完全不用strtok,这样就不会有状态冲突的问题了。比如在is_ingredient里这样写:int is_ingredient(const char* str){ char tmp[1024]; strncpy(tmp, str, sizeof(tmp)); tmp[sizeof(tmp)-1] = '\0'; char delim = ' '; // 你的分隔符,要是有多个可以加判断 char* start = tmp; while (*start != '\0') { // 找到当前token的结尾 char* end = start; while (*end != '\0' && *end != delim) { end++; } // 临时把分隔符换成'\0',拿到完整的token char temp = *end; *end = '\0'; // 这里写你处理token的代码,比如判断是不是食材 // printf("当前处理的token: %s\n", start); // 恢复分隔符(其实tmp是临时数组,不恢复也不影响) *end = temp; // 移动到下一个token的开头 start = (*end != '\0') ? end + 1 : end; } return 1; }
总结一下,核心就是避免跨函数共享strtok的静态状态,要么用带独立状态的可重入函数,要么自己实现无状态的分词逻辑,这样原指针所在的分词流程就不会被打断了。
备注:内容来源于stack exchange,提问作者user26502233

