寻求可完整读取文件内容至字符串的fgets替代函数
解决方案:一次性读取短文本文件完整内容到字符串
原代码的问题分析
- 内存分配错误:
malloc(sizeof(50*256*sizeof(char)))是错误写法,sizeof()会计算括号内表达式的字节大小(通常是size_t类型的大小,约8字节),实际应该直接分配50*256字节的空间。 - fgets参数限制:你传入的第二个参数是100,这会导致fgets最多读取99个字符就停止(加上结束符),这才是内容被截断的核心原因——fgets并不会在空格处截断,只会在换行符、EOF或达到指定长度时停止。
方法一:用fread直接读取(适合已知文件大小上限的场景)
因为你已经明确文件长度小于50*256=12800字符,直接用fread一次性读取全部内容,之后手动添加字符串结束符即可:
FILE *rules_text_file; const size_t MAX_FILE_SIZE = 50 * 256; // 分配足够空间,预留一个字节存结束符 char *rules = malloc(MAX_FILE_SIZE + 1); if (!rules) { // 内存分配失败,做错误处理 return -1; } // 确保文件已正确打开(比如用fopen("your_file_path", "r")) // ... // 读取文件内容,最多读MAX_FILE_SIZE字节 size_t bytes_read = fread(rules, 1, MAX_FILE_SIZE, rules_text_file); if (bytes_read == 0 && ferror(rules_text_file)) { // 读取发生错误,释放内存后返回 free(rules); return -1; } // 手动添加字符串结束符,避免后续字符串操作出错 rules[bytes_read] = '\0'; printf("%s\n", rules); fclose(rules_text_file); free(rules); return 0;
方法二:先获取文件大小再精确读取(更严谨)
如果想根据实际文件大小分配内存,可以先获取文件长度,再针对性读取:
FILE *rules_text_file = fopen("your_file_path", "r"); if (!rules_text_file) { // 文件打开失败处理 return -1; } // 移动文件指针到末尾,获取文件大小 fseek(rules_text_file, 0, SEEK_END); long file_size = ftell(rules_text_file); // 移回文件开头准备读取 fseek(rules_text_file, 0, SEEK_SET); // 检查文件大小是否超出限制或获取失败 if (file_size < 0 || file_size > 50*256) { fclose(rules_text_file); return -1; } // 分配刚好足够的内存+1字节存结束符 char *rules = malloc(file_size + 1); if (!rules) { fclose(rules_text_file); return -1; } // 读取全部内容 size_t bytes_read = fread(rules, 1, file_size, rules_text_file); rules[bytes_read] = '\0'; printf("%s\n", rules); fclose(rules_text_file); free(rules); return 0;
关键注意事项
- 无论用哪种方法,必须手动添加
'\0':fread不会自动为字符串添加结束符,缺少的话会导致printf、字符串拷贝等操作出现未定义行为。 - 内存分配后一定要检查是否成功,避免空指针访问。
- 如果文件是二进制模式,需要注意打开方式,但你这里是文本文件,用
"r"模式打开即可。
内容的提问来源于stack exchange,提问作者Its me
相关产品推荐
相关产品推荐

