You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用fread()实现文件部分读取并获得预期输出?

问题分析与解决方案

你的代码无法得到预期输出,核心原因有两个:

  1. 缺少C字符串终止符:你定义的char buffer[3]刚好容纳每次读取的3个字节,没有多余空间存储字符串必需的'\0'。sscanf处理无终止符的字符串会触发未定义行为,可能导致解析失败或逻辑异常。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 12:07:12