递归生成组合时n≥8输出文件仅254行后变为NULL的问题排查
问题分析与解决
你的代码核心问题是递归过程中反复打开文件却几乎不关闭,导致系统可用的文件句柄被耗尽——Windows默认进程能打开的文件句柄数量有限(通常是256左右),当n=8、9时组合数暴增,打开的未关闭文件数很快达到上限,后续fopen就会返回NULL,自然写不进去内容。
代码中的具体问题
- 每次调用
comb都执行fopen(filename, "a"),但只有在curlen == 0 && num[0] == n这一个极端条件下才会关闭文件,其他所有递归分支打开的文件都没关,句柄一直被占用。 - 字符转换的写法
num[i] + ''虽然能得到正确的字母(因为''的ASCII是96,1+96=97='a'),但可读性很差,换成num[i] + 'a' - 1`更直观。
修复后的代码
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> // 递归生成组合并写入文件 void comb(int n, int curlen, int start, int num[], FILE* fptr) { // 输出当前非空组合 if (curlen > 0) { for (int i = 0; i < curlen; i++) { fprintf(fptr, "%c", num[i] + 'a' - 1); } fprintf(fptr, " "); } // 递归生成更长的组合 for (int i = start; i <= n; i++) { num[curlen] = i; comb(n, curlen + 1, i + 1, num, fptr); } } int main() { int n; int num[20] = {0}; char filename[20] = "output-0.txt"; scanf("%d", &n); filename[7] = n + '0'; // 构造目标文件名 FILE* fptr = fopen(filename, "w"); // 用w模式清空旧内容,避免重复 if (fptr == NULL) { printf("无法打开文件!\n"); return 1; } comb(n, 0, 1, num, fptr); fclose(fptr); // 最后统一关闭文件 system("pause"); return 0; }
关键修改说明
- 文件句柄复用:在
main中一次性打开文件,将指针传递给递归函数,全程仅占用一个文件句柄,彻底解决句柄耗尽问题。 - 递归逻辑简化:移除冗余的
flag参数,直接在递归流程中先输出当前组合,再生成更长的组合,逻辑更清晰易读。 - 文件模式优化:使用
"w"模式打开文件,每次运行会清空旧内容(若需要追加可改回"a",但生成组合场景通常需要覆盖旧结果)。 - 可读性提升:将字符转换逻辑改为直观的
num[i] + 'a' -1,避免依赖''的ASCII值这种隐晦写法。
内容的提问来源于stack exchange,提问作者b1841837
相关产品推荐
相关产品推荐

