嵌套for循环的fprintf未写入首个变量名,求问题排查与解决
问题排查与解决方案:CSV表格缺失第一个变量名par1
我来帮你定位并解决这个par1缺失的问题!结合你提供的代码和现象,核心问题出在read_name函数的内存管理和逻辑细节上,下面一步步分析:
问题根源分析
返回局部变量指针导致未定义行为
read_name函数中,par_name = line将局部数组line的地址赋值给返回指针。当函数执行完毕,line的栈内存会被释放,后续在store函数中使用这个指针时,内存已经失效,可能被后续函数调用覆盖,这就是par1内容丢失的主要原因。字符串处理不完整
你仅用strtok(line, "\n")去掉了换行符,但没有从行中提取出参数名本身(比如从par1 0 1 0.5中分离出par1),虽然你说单独测试read_name能输出正确字符串,但这只是栈内存未被覆盖时的偶然现象。资源处理不完善
如果文件读取未找到目标行,par_name会返回未初始化的野指针;且文件关闭逻辑仅在找到目标行时执行,存在资源泄漏风险。
修复后的代码实现
1. 重构read_name函数(解决内存和字符串提取问题)
#include <stdio.h> #include <stdlib.h> #include <string.h> char *read_name(int par_id, char *filepath) { char *par_name = NULL; // 计算参数名所在的目标行号(对应你文本文件的两行一组格式) int target_line = (2 * par_id) - 2; int count = 0; FILE *file = fopen(filepath, "r"); if (file == NULL) { fprintf(stderr, "\n\n ERROR IN FUNCTION READ_NAME\n\nTEXT FILE CANNOT BE OPENED\n\n"); return NULL; } char line[256]; while (fgets(line, sizeof(line), file) != NULL) { if (count == target_line) { // 分割出第一个空格/换行前的内容(即参数名) char *token = strtok(line, " \n"); if (token != NULL) { // 动态分配内存存储参数名,避免局部变量问题 par_name = malloc(strlen(token) + 1); if (par_name != NULL) { strcpy(par_name, token); } } break; // 找到目标行后立即退出循环 } count++; } fclose(file); // 确保文件始终被关闭 if (par_name == NULL) { fprintf(stderr, "\n\n WARNING: PARAMETER NAME FOR ID %d NOT FOUND\n\n", par_id); } return par_name; }
2. 修复store函数(添加内存释放和健壮性处理)
int store(int par_num, float sim_num, float **tab_param, char *filepath, char *tablepath) { int j; char *name = NULL; FILE* sim_table = fopen(tablepath, "w"); if (sim_table == NULL) { fprintf(stderr, "\n\n ERROR: CANNOT OPEN TABLE FILE FOR WRITING\n\n"); return -1; } // 写入表头第一部分 fprintf(sim_table, "simulation_number"); // 简化循环条件,逻辑更清晰 for(j=1; j <= par_num; j++){ name = read_name(j, filepath); if (name != NULL) { if(j == par_num){ fprintf(sim_table, ",%s\n", name); } else { fprintf(sim_table, ",%s", name); } free(name); // 释放动态分配的内存,避免泄漏 name = NULL; } else { // 参数名获取失败时写入占位符,避免表格格式错乱 fprintf(sim_table, ",unknown_par%d", j); } } fclose(sim_table); return 0; }
为什么之前par1会缺失?
在旧代码中,read_name(1)返回的局部数组指针,在函数返回后内存被回收。当调用read_name(2)时,栈内存被重新利用,导致第一个返回的指针指向的内容被覆盖,所以fprintf时par1的位置变成空白;而后续参数因为刚调用完read_name,栈内存还未被覆盖,所以能正常显示。修复后使用动态分配内存,彻底避免了这个问题。
内容的提问来源于stack exchange,提问作者Goûtay
相关产品推荐
相关产品推荐

