Linux环境下C语言读取文件到字符串时fgetc返回-1及乱码问题
问题根因与修复方案
核心错误点
- fgetc返回-1的直接原因:使用
fseek(file, 0, SEEK_END)获取文件长度后,未调用rewind(file)或者fseek(file, 0, SEEK_SET)将文件指针重置到文件开头,后续读取操作直接从文件结束位置开始,拿到的全是EOF(即-1),存入数组后对应字节为0xFF,在终端输出就会显示为菱形问号。 - 输出末尾随机乱码原因:C语言字符串要求以
\0作为结束标记,你的数组长度仅等于文件实际字节数,没有预留1字节的空间存储结束符,调用printf("%s")时会越界读取数组后的随机内存值,所以每次运行显示的末尾乱码都不一样。 - 内容拷贝逻辑完全错误:
readFile函数内的fileContent是函数栈上的局部数组,函数执行结束后该内存会被自动回收,且*outString = fileContent属于类型不匹配的错误赋值:*outString是char类型,fileContent是指针类型,该操作既没有把文件内容拷贝到main函数传入的fileContents数组中,还会造成内存访问错误。 - 其他常见错误:
fileLength函数打开文件后没有调用fclose,存在文件资源泄漏- 文本模式下调用
fseek+ftell获取文件长度属于C标准未定义行为,建议使用二进制模式rb打开文件 - 调用
exit函数需要引入<stdlib.h>头文件,否则编译会有隐式声明警告 - 打印指针地址应该使用
%p格式符,%x仅适用于输出无符号整数 - main函数调用
readFile时传&fileContents属于多余操作,数组名本身就是首元素地址,直接传fileContents即可
修复后完整代码
#include <stdio.h> #include <stdlib.h> int fileLength(const char filePath[]); void readFile(const char filePath[], char* outString, int bufLen); int main() { int len = fileLength("Files/test"); // 多预留1字节存字符串结束符 char fileContents[len + 1]; readFile("Files/test", fileContents, len); printf("DEBUG: Address of fileContents is %p\n", (void*)fileContents); printf("File contents:\n%s\n", fileContents); return 0; } int fileLength(const char filePath[]) { FILE* file; if ((file = fopen(filePath, "rb")) == NULL) { printf("ERROR: File (%s) cannot be opened.\n", filePath); return -1; } fseek(file, 0, SEEK_END); int len = ftell(file); fclose(file); return len; } void readFile(const char filePath[], char* outString, int bufLen) { FILE* file; printf("DEBUG: File path is %s\n", filePath); if ((file = fopen(filePath, "rb")) == NULL) { printf("ERROR: File (%s) cannot be opened.\n", filePath); exit(1); } fseek(file, 0, SEEK_END); int fileLength = ftell(file); printf("DEBUG: File length is %i\n", fileLength); // 重置文件指针到开头 rewind(file); printf("DEBUG: File contents as digits:\n"); for (int i = 0; i < fileLength && i < bufLen; i++) { outString[i] = fgetc(file); printf("%d ", outString[i]); } // 补充字符串结束符 outString[fileLength < bufLen ? fileLength : bufLen] = '\0'; printf("\n"); printf("DEBUG: Contents of file are:\n%s\n", outString); fclose(file); printf("DEBUG: outString is pointing to %p\n", (void*)outString); }
内容的提问来源于stack exchange,提问作者Dreary35
相关产品推荐
相关产品推荐

