C语言函数返回异常:无法获取新文件名的技术咨询
问题解决:递归调用后无法获取最终文件名的修复方案
原代码的核心问题是:new_data函数递归调用时,始终返回当前栈帧的输入参数str,而非用户最终确认的文件名。同时代码还存在文件读取逻辑错误、缓冲区溢出风险等问题,以下是两种可行的修复方案:
方案一:使用输出参数传递最终文件名
通过新增输出参数,直接将最终确定的文件名写入调用者提供的缓冲区,避免递归返回值丢失的问题。
修改后代码
#include<stdio.h> #include<string.h> void new_data(char *input_str, char *result_str, size_t result_size) { FILE *name_file, *data_file; // 以读写模式打开,文件不存在则创建 name_file = fopen("name_file.txt", "r+"); if (!name_file) { name_file = fopen("name_file.txt", "w+"); } char file_name[30]; char option; int exists = 0; // 修正读取逻辑:先读取再判断,避免feof的误判 rewind(name_file); while (fscanf(name_file, "%s", file_name) == 1) { if (strcmp(file_name, input_str) == 0) { exists = 1; break; } } if (exists) { printf("文件已存在,是否覆盖 [y n]: "); scanf(" %c", &option); if (option == 'y') { data_file = fopen(input_str, "w"); if (data_file) fclose(data_file); // 写入最终文件名到输出参数 strncpy(result_str, input_str, result_size); result_str[result_size - 1] = '\0'; } else { printf("请输入新文件名: "); char new_name[30]; scanf(" %s", new_name); // 递归调用,直接复用输出参数传递结果 new_data(new_name, result_str, result_size); } } else { data_file = fopen(input_str, "w"); if (data_file) { fclose(data_file); fseek(name_file, 0, SEEK_END); fprintf(name_file, "%s\n", input_str); } strncpy(result_str, input_str, result_size); result_str[result_size - 1] = '\0'; } fclose(name_file); } int main(int argc, char **argv) { if (argc < 2) { printf("请传入初始文件名参数\n"); return 1; } char res[30]; new_data(argv[1], res, sizeof(res)); printf("最终确定的文件名: %s\n", res); return 0; }
关键改动说明
- 新增
result_str输出参数,直接存储最终文件名,递归时层层传递该参数 - 修正文件打开模式为
r+,并处理文件不存在的情况,确保能读取已有内容 - 用
fscanf的返回值判断读取是否成功,替代错误的while(!feof())逻辑 - 使用
strncpy替代strcpy,并手动添加字符串结束符,防止缓冲区溢出
方案二:返回动态分配的字符串
通过malloc动态分配内存存储最终文件名,递归时将底层的返回值逐层向上传递,确保main函数能拿到最终结果。
修改后代码
#include<stdio.h> #include<string.h> #include<stdlib.h> char *new_data(char *input_str) { FILE *name_file, *data_file; name_file = fopen("name_file.txt", "r+"); if (!name_file) { name_file = fopen("name_file.txt", "w+"); } char file_name[30]; char option; int exists = 0; char *result = NULL; rewind(name_file); while (fscanf(name_file, "%s", file_name) == 1) { if (strcmp(file_name, input_str) == 0) { exists = 1; break; } } if (exists) { printf("文件已存在,是否覆盖 [y n]: "); scanf(" %c", &option); if (option == 'y') { data_file = fopen(input_str, "w"); if (data_file) fclose(data_file); // 分配内存存储文件名 result = malloc(strlen(input_str) + 1); if (result) strcpy(result, input_str); } else { printf("请输入新文件名: "); char new_name[30]; scanf(" %s", new_name); // 递归调用,接收底层返回的动态分配字符串 result = new_data(new_name); } } else { data_file = fopen(input_str, "w"); if (data_file) { fclose(data_file); fseek(name_file, 0, SEEK_END); fprintf(name_file, "%s\n", input_str); } result = malloc(strlen(input_str) + 1); if (result) strcpy(result, input_str); } fclose(name_file); return result; } int main(int argc, char **argv) { if (argc < 2) { printf("请传入初始文件名参数\n"); return 1; } char *res = new_data(argv[1]); if (res) { printf("最终确定的文件名: %s\n", res); free(res); // 必须释放动态分配的内存,避免泄漏 } else { printf("内存分配失败\n"); } return 0; }
关键改动说明
- 函数返回动态分配的字符串,递归时直接将底层结果向上传递
- main函数使用完结果后必须调用
free释放内存,避免内存泄漏 - 同样修复了文件读取逻辑的错误,确保能正确检测文件名是否存在
原代码的其他问题修正点
- 原代码中
scanf(" %s",&file_name)的&是错误的,file_name作为数组名本身就是指针,无需加取地址符 while(!feof(name_file))的逻辑错误,feof是在读取失败后才会置位,会导致最后一次读取重复内容- 递归时
strcpy(res,new_data(file_name))的操作无效,因为res是局部数组,最终函数返回的仍是初始的str
内容的提问来源于stack exchange,提问作者mah011
相关产品推荐
相关产品推荐

