如何使用fread()实现文件部分读取并获得预期输出?
问题分析与解决方案
你的代码无法得到预期输出,核心原因有两个:
- 缺少C字符串终止符:你定义的
char buffer[3]刚好容纳每次读取的3个字节,没有多余空间存储字符串必需的'\0'。sscanf处理无终止符的字符串会触发未定义行为,可能导致解析失败或逻辑异常。 sscanf("%d")的解析限制:%d格式符会自动跳过空白字符(包括换行\n),遇到非数字字符就停止解析。第二次读取的"4\n1"中,sscanf读到\n就会终止,只会解析出4,完全忽略后面的1;第三次读取的"0\n"因为没有终止符,sscanf也无法正确解析。
修正后的代码方案
方案一:累积跨分段的数字字符(贴合按3字节读取的需求)
这个方案会把分段读取时被拆分的数字字符(比如4\n1里的4和1)累积起来,统一解析成整数:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> int main() { int value = 0; // 扩大buffer,预留一个字节存字符串终止符 char buffer[4]; // 用来累积跨分段的数字字符 char temp[10] = {0}; size_t temp_len = 0; FILE* channel_file = fopen("test_file.txt", "rb"); if (!channel_file) { perror("Failed to open file"); return 1; } size_t read_bytes; while ((read_bytes = fread(buffer, sizeof(char), 3, channel_file)) > 0) { // 手动添加字符串终止符,避免未定义行为 buffer[read_bytes] = '\0'; // 遍历当前读取的每个字节 for (size_t i = 0; i < read_bytes; i++) { if (isdigit(buffer[i])) { // 是数字字符就加入临时字符串 if (temp_len < sizeof(temp) - 1) { temp[temp_len++] = buffer[i]; temp[temp_len] = '\0'; } } else { // 遇到非数字字符,解析临时字符串里的整数并输出 if (temp_len > 0) { sscanf(temp, "%d", &value); printf("%d\n", value); // 清空临时字符串,准备下次累积 temp_len = 0; memset(temp, 0, sizeof(temp)); } } } } // 处理文件结束后剩下的数字字符 if (temp_len > 0) { sscanf(temp, "%d", &value); printf("%d\n", value); } fclose(channel_file); return 0; }
方案二:直接提取分段内的数字字符(简洁实现预期输出)
这个方案会直接从每个3字节分段中提取所有数字字符,拼接后解析:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> int main() { int value = 0; char buffer[4]; FILE* channel_file = fopen("test_file.txt", "rb"); if (!channel_file) { perror("Failed to open file"); return 1; } size_t read_bytes; while ((read_bytes = fread(buffer, sizeof(char), 3, channel_file)) > 0) { // 添加终止符,确保字符串合法 buffer[read_bytes] = '\0'; char num_str[4] = {0}; size_t num_idx = 0; // 过滤当前分段中的数字字符 for (size_t i = 0; i < read_bytes; i++) { if (isdigit(buffer[i])) { if (num_idx < sizeof(num_str) - 1) { num_str[num_idx++] = buffer[i]; } } } // 如果提取到数字,解析并输出 if (num_idx > 0) { sscanf(num_str, "%d", &value); printf("%d\n", value); } } fclose(channel_file); return 0; }
关键修正点
- 把
buffer扩容到4字节,每次读取后手动添加'\0',彻底解决未定义行为问题。 - 用
isdigit函数过滤非数字字符,确保数字字符被正确拼接,避免sscanf因空白字符提前终止解析。 - 增加了文件打开失败的错误处理,提升程序健壮性。
内容的提问来源于stack exchange,提问作者user22219231
相关产品推荐
相关产品推荐

