VS2022环境下C语言逐字符读写txt文件代码及报错咨询
C语言逐字符读写文件问题解析与优化方案
一、编译错误与警告原因
错误1:未初始化局部变量f + 类型不兼容警告
fopen函数第一个参数要求传入待读取文件的名字符串,你写的FILE* f = fopen(f, "r");直接把还未初始化的FILE*类型变量f当参数传入,既触发了未初始化变量调用错误,也和fopen要求的const char*参数类型不匹配,就是你看到的类型转换警告的来源。另外main函数返回值为int类型,判断文件打开失败直接return NULL也是错误的,应该返回负整数错误码。
错误2:未初始化局部变量x
你定义int* x;时没有给任何初始值,直接做if (x == NULL)判断,此时x是野指针,值完全随机,判断没有任何意义。同时你在while循环内又写了int* x = calloc(i, sizeof(double));,相当于定义了一个和外层x同名的局部变量,仅在循环体内部有效,外层的x从头到尾都没有被赋值,最后free(x)时调用的还是外层的野指针,自然会触发未初始化变量错误。
二、原有逻辑疑问解答
- 读到EOF直接跳出会不会导致文件没读完?不会。fgetc返回EOF的唯一触发条件就是已经读到文件末尾,此时跳出循环刚好完整读完了所有内容,不会出现遗漏。
- calloc分配内存后要不要做空指针校验?必须要。calloc和malloc、realloc一样,内存不足时会分配失败返回NULL,不管它会不会自动初始化内存,都必须做空指针校验,避免空指针访问崩溃。
三、原有逻辑其他不合理点
- 每次循环都重新调用calloc分配内存,之前分配的内存没有释放也没有保留,会产生严重的内存泄漏,而且每次分配的新内存只会存当前一个字符,之前读取的字符全部丢失。
- 字符存储类型错误:fgetc的返回值是int类型(因为EOF是超出char范围的int值),你用char类型存count会导致无法正确判断EOF。
- 数组越界:你分配了i个元素的数组,合法下标是0~i-1,直接给x[i]赋值会越界访问,导致内存损坏。
- 不需要把整个大文件全部加载到内存:练习大文件逐字符读写完全可以读一个字符就写一个字符,内存占用只有几个变量的大小,不会因为文件太大导致内存不足。
- 写入循环的终止条件错误:你没有把EOF写入x数组,循环永远不会碰到终止条件,会一直越界访问数组直到崩溃。
四、优化实现方案(符合逐字符读写大文件的练习要求)
不需要把整个文件加载到内存,读一个写一个,性能高内存占用极低,代码如下:
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> int main(void) { // 打开读文件,替换为你实际的输入文件名 FILE* f = fopen("input.txt", "r"); if (f == NULL) { return -1; } // 打开写文件 FILE* g = fopen("otherfile.txt", "w"); if (g == NULL) { fclose(f); return -2; } int count; // 必须用int存fgetc返回值才能正确判断EOF // 逐字符读写 while ((count = fgetc(f)) != EOF) { fputc(count, g); } // 收尾操作 fclose(f); fclose(g); return 0; }
如果你一定要练习动态内存存储整个文件的写法,可以用realloc动态扩容数组,不要每次循环都重新calloc。
内容的提问来源于stack exchange,提问作者Gabriel Burzacchini
相关产品推荐
相关产品推荐

