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

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释放内存,避免内存泄漏
  • 同样修复了文件读取逻辑的错误,确保能正确检测文件名是否存在

原代码的其他问题修正点

  1. 原代码中scanf(" %s",&file_name)的&是错误的,file_name作为数组名本身就是指针,无需加取地址符
  2. while(!feof(name_file))的逻辑错误,feof是在读取失败后才会置位,会导致最后一次读取重复内容
  3. 递归时strcpy(res,new_data(file_name))的操作无效,因为res是局部数组,最终函数返回的仍是初始的str

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 06:40:51