C语言使用strtok拆分字符串转结构体插入列表时旧数据被覆盖如何解决
问题核心原因
你遇到的问题本质是浅拷贝导致所有结构体的字符串指针指向同一块栈缓冲区,具体逻辑如下:
- 你在
readDataFromFile函数中定义的char buff[1024]是栈上的临时缓冲区,每次fgets读取新行都会覆盖这块内存的内容 strtok返回的指针都是指向buff内部的偏移地址,你直接把这些指针赋值给Product结构体的code、name、unit成员,相当于所有结构体的字符串指针都指向这块公共的buff内存- 每次循环覆盖buff后,之前所有结构体指向的字符串内容都会同步更新,最终所有成员的值都和最后一行的内容一致
另外代码还有个小bug:printf("[readDataFromFile]INFO: Product Name after conver: %s, Current length %d\n", product.name, lengthPtr); 这里你传的是lengthPtr指针本身,应该传*lengthPtr才能输出正确的列表长度。
修复方案
- 转换字符串到结构体时,不要直接赋值指针,要为每个字符串单独申请堆内存拷贝内容,修改
convertStringToProduct的赋值逻辑:
// 先定义一个字符串拷贝工具函数,环境支持strdup可以直接用strdup char* my_strdup(const char* src) { char* dst = malloc(strlen(src) + 1); if(dst) strcpy(dst, src); return dst; } Product convertStringToProduct(char *strPtr) { char *str = strPtr; char* regex = "|"; char* token = strtok(str,regex); char* code; char* name; char* unit; int quantity; char* dateAdd; bool status; int i = 0; while(true){ if(i==0){ code = my_strdup(token); }else if(i == 1){ name = my_strdup(token); }else if(i == 2){ quantity = atoi(token); }else if(i == 3){ unit = my_strdup(token); }else if(i == 4){ dateAdd = my_strdup(token); }else if(i == 5){ status = checkBoolean(token); }else{ break; } i++; token = strtok(NULL, "|"); } date fdateAdd = convertStringToDate(dateAdd); free(dateAdd); // dateAdd是临时变量,用完释放避免泄漏 Product pro = {code, name, quantity, unit, fdateAdd.day, fdateAdd.month, fdateAdd.year, status}; return pro; }
补充异常处理:
realloc失败后除了打印错误,要加exit(EXIT_FAILURE);终止程序,避免后续空指针访问。程序退出前释放内存避免泄漏,在main函数打印完列表后添加:
for( i=0; i<length; ++i) { free(listProduct[i].code); free(listProduct[i].name); free(listProduct[i].unit); } free(listProduct);
内容的提问来源于stack exchange,提问作者Lam Hoang
相关产品推荐
相关产品推荐

