C语言读取文件到512长字符数组 剩余空位填'x'代码问题排查
代码存在的核心问题
- 未初始化字符数组:栈上分配的
str[512]默认存储随机垃圾值,不会自动填充'\0',原有填充逻辑靠找'\0'判断有效内容结尾完全不成立,没被写入的位置本身就是乱码,输出自然混乱。 - 文件读取逻辑存在多个漏洞:
- 没有判断
fopen返回值,文件不存在、无读取权限时直接操作空指针会直接崩溃 - 用
while(!feof(fp))做循环条件是C语言经典错误写法,feof只有在读操作已经碰到EOF之后才会返回真值,会导致多读取一次无效的EOF值 - 写入数组时没做长度校验,一旦文件内有效小写字母数量超过512,就会发生数组越界写,破坏相邻内存数据
- 传给
tolower的参数没做类型强转,遇到编码值为负的字符会触发未定义行为 - 读完文件没有调用
fclose,存在资源泄漏
- 没有判断
- 填充逻辑设计错误:原有逻辑从下标0开始遍历数组找
'\0',但数组未初始化时大部分位置是随机值不是'\0',这些位置根本不会被替换成'x';实际上读取循环结束时,变量i的值刚好就是有效字符的总长度,直接从这个位置开始填充即可,完全不需要遍历全数组找结尾。
可直接运行的修正版本
#include <stdio.h> #include <ctype.h> int main() { FILE *fp; char str[512]; int c, i = 0; fp = fopen("k1.txt", "r"); if (fp == NULL) { perror("文件打开失败"); return 1; } // 读入时同步做长度限制,避免越界,直接判断fgetc返回值替代错误的feof判断 while (i < 512 && (c = fgetc(fp)) != EOF) { c = tolower((unsigned char)c); // 仅保留小写字母,其余字符全部跳过 if (c >= 'a' && c <= 'z') { str[i] = c; i++; } } fclose(fp); // 从有效内容末尾开始填充'x'直到数组满512位 for (; i < 512; i++) { str[i] = 'x'; } // 如需验证结果可放开下方注释打印数组内容 // for (int j = 0; j < 512; j++) putchar(str[j]); return 0; }
关键修改说明
- 补全了依赖的头文件,避免隐式函数声明导致的编译警告、运行异常
- 增加文件打开失败的判断逻辑,提前报错退出
- 重写读取循环条件,直接判断
fgetc返回值是否为EOF,同时加入i < 512的边界限制,从根源杜绝数组越界 - 去掉冗余的换行判断,
tolower传参时强转为unsigned char规避未定义行为 - 读取结束后立刻关闭文件释放资源
- 填充
'x'时直接从有效长度i的位置开始写入,直到数组最后一个下标(511)为止,不依赖数组初始值,保证数组后段全部被填充为'x',总长度刚好512。
内容的提问来源于stack exchange,提问作者Bananatoid
相关产品推荐
相关产品推荐

