桌面正常的C文件操作代码在RAR中运行异常,如何修复?
解决RAR压缩包内C代码生成文件为空的问题
两段C代码分别实现随机数文件生成和质数提取功能:
- 第一段生成100个随机数写入
numbers.txt - 第二段读取
numbers.txt,提取其中质数写入numbers2.txt
单独在桌面运行两段代码一切正常,但打包到同一RAR压缩包后运行,第二段代码生成的numbers2.txt为空,以下是问题分析和解决办法:
第一段代码(生成随机数文件)
#include <stdio.h> #include <stdlib.h> int main() { FILE *fp; int number[100]; fp = fopen("numbers.txt", "w"); for (int i = 0; i < 100; i++) { number[i] = rand() % 1000; fprintf(fp, "%d\n", number[i]); } fclose(fp); return 0; }
第二段代码(提取质数)
#include <stdio.h> #include <stdlib.h> int main() { FILE *fp; FILE *fp1; int number, count; fp = fopen("numbers.txt", "r"); fp1 = fopen("numbers2.txt", "w"); while (!feof(fp)) { count = 0; fscanf(fp, "%d", &number); for (int i = 2; i < number / 2; i++) { if (number % i == 0) { count++; } } if (count == 0 && number >= 2) { fprintf(fp1, "%d\n", number); } } fclose(fp); fclose(fp1); return 0; }
问题原因分析
文件路径与工作目录不匹配
从RAR压缩包直接运行程序时,系统当前工作目录可能不是程序解压后的文件夹,导致第二段代码找不到numbers.txt(或读取到其他位置的空文件),最终生成空的numbers2.txt。未检查文件打开状态
两段代码都未判断fopen的返回值,如果numbers.txt不存在或无法打开,fp会是NULL,后续读取操作直接失败,但程序无错误提示,默默生成空文件。错误使用
feof作为循环条件while (!feof(fp))存在逻辑缺陷:feof只有在尝试读取超过文件末尾时才会返回真,导致最后一次读取失败后仍执行质数判断逻辑,可能读取到无效值,引发未定义行为。质数判断逻辑存在bug
原代码循环条件i < number / 2会漏掉部分非质数的判断(比如number=4时循环不执行,错误判定为质数),虽不是文件为空的直接原因,但会影响结果准确性。
解决办法
1. 强制检查文件打开状态
在两段代码中,调用fopen后立即检查返回值,确保文件成功打开:
- 第一段代码修改:
fp = fopen("numbers.txt", "w"); if (fp == NULL) { perror("无法创建numbers.txt"); return 1; }
- 第二段代码修改:
fp = fopen("numbers.txt", "r"); if (fp == NULL) { perror("无法打开numbers.txt"); return 1; } fp1 = fopen("numbers2.txt", "w"); if (fp1 == NULL) { perror("无法创建numbers2.txt"); fclose(fp); return 1; }
2. 修正循环条件,替代feof
用fscanf的返回值判断是否成功读取数据,替换!feof(fp):
while (fscanf(fp, "%d", &number) == 1) { // 质数判断逻辑 }
fscanf成功读取一个整数时返回1,遇到文件末尾或读取失败时返回EOF,能准确控制循环结束时机。
3. 确保工作目录正确
- 不要直接从RAR压缩包内运行程序,先手动解压所有文件到同一文件夹,再运行程序;
- 若需自动处理路径,可通过平台API获取程序自身目录,再拼接文件名(如Windows下用
GetModuleFileName,Linux下用readlink),确保文件读写路径正确。
4. 修正质数判断逻辑
优化质数判断的循环条件,避免错误判定:
count = 0; if (number < 2) { continue; } // 2是唯一的偶质数 if (number == 2) { fprintf(fp1, "%d\n", number); continue; } // 偶数大于2直接排除 if (number % 2 == 0) { continue; } // 只检查奇数因子,循环到平方根即可 for (int i = 3; i * i <= number; i += 2) { if (number % i == 0) { count++; break; // 找到因子后直接退出循环 } } if (count == 0) { fprintf(fp1, "%d\n", number); }
内容的提问来源于stack exchange,提问作者Beyza
相关产品推荐
相关产品推荐

