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

C语言程序生成文件名时偶现异常字符的问题求助

C程序生成文件名时出现随机异常字符的修复方案

问题背景

程序需实现两个功能:

  • 接收命令行参数,移除标点并转小写后拼接成字符串
  • 为字符串添加日期前缀生成最终文件名

执行命令:

./cprog -md I am cre,ating a .md file

预期生成文件名:

2023_12_15_i_am_cre_ating_a__md_file.md

但约25%概率出现异常输出:

'2023_12_15_'$''\002'i_am_cre_ating_a__md_file.md'

问题代码片段

标点移除与参数拼接代码

for ( int arg = 0; arg < argc; arg++ ){

    for ( int let = 0; let < strlen(argv[arg]); let++ ){

        if ( !ispunct( argv[arg][let] ) ){

            argv[arg][let] = tolower( argv[arg][let] );

        } else {

            argv[arg][let] = 95;

        }

    }

    strcat( filename, argv[arg] );

}

日期生成与文件名拼接代码

time_t rawtime = time(NULL);
struct tm *ptm = localtime(&rawtime);
char filename_date[12];
char result[ strlen(filename_date) + strlen(filename) ];
strftime( filename_date, sizeof(filename_date), "%Y_%b_%d", ptm );
sprintf( result, "%s_%s.md", filename_date, filename );
strcpy( filename, result );
create_md( filename );

核心问题分析

  1. 未初始化数组的长度计算:
    char result[ strlen(filename_date) + strlen(filename) ];中,filename_date是未初始化的局部数组,内存为随机垃圾值,strlen会读取到随机的终止位置,导致result数组大小不足,后续sprintf写入时越界,破坏内存产生异常字符。

  2. 直接修改argv内存的风险:
    argv指向的命令行参数内存在部分系统中是只读的,直接修改会触发未定义行为;同时若filename未初始化为空字符串,strcat操作也会读取随机内存。

  3. 日期格式符不匹配预期:
    代码中用%b(月份缩写,如Dec),但预期是数字月份,需改为%m。

修复代码示例

修复后的参数处理代码

// 确保filename预先初始化为空,比如:
char filename[1024] = {0};

for (int arg = 0; arg < argc; arg++) {
    char temp[256] = {0}; // 临时缓冲区处理单个参数
    size_t arg_len = strlen(argv[arg]);
    for (int let = 0; let < arg_len; let++) {
        // 用unsigned char避免tolower/ispunct处理负数值的未定义行为
        unsigned char c = argv[arg][let];
        if (!ispunct(c)) {
            temp[let] = tolower(c);
        } else {
            temp[let] = '_';
        }
    }
    strcat(filename, temp);
}

修复后的日期与文件名拼接代码

time_t rawtime = time(NULL);
struct tm *ptm = localtime(&rawtime);
char filename_date[12];
// 先填充日期字符串,确保内容有效
strftime(filename_date, sizeof(filename_date), "%Y_%m_%d", ptm);

// 计算所需缓冲区大小,包含日期、下划线、原文件名、.md和终止符
size_t result_size = strlen(filename_date) + strlen(filename) + 4;
char *result = malloc(result_size);
if (result == NULL) {
    perror("malloc failed");
    return 1;
}

sprintf(result, "%s_%s.md", filename_date, filename);
strcpy(filename, result);
free(result); // 释放动态分配的内存

create_md(filename);

关键修复点总结

  • 初始化所有字符串缓冲区,避免读取随机内存
  • 不直接修改argv,改用临时缓冲区处理参数
  • 先填充日期数组再计算最终文件名的缓冲区大小,或使用足够大的固定缓冲区
  • 修正日期格式符为%Y_%m_%d以匹配预期的数字月份格式

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 02:34:58