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

为何使用fread从stdin读取时无法终止?如何解决?

解决fread从stdin读取时循环无法终止的问题

当你从终端交互式输入时,fread会一直阻塞等待输入——因为终端没有天然的EOF标识,必须手动触发(如Ctrl+D)才会让fread返回0,这就是循环停不下来的核心原因。要实现无需手动触发EOF的正常终止,可以从以下两种场景入手解决:

1. 为交互式输入设置结束标记

约定一个特定字符串作为输入结束信号,每次读取后检查缓冲区内容,匹配到标记就终止循环。比如用"###END###"作为结束标记(可根据需求调整),修改后的代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define END_MARK "###END###"

int main(int argc, char *argv[])
{
    if (argc != 2) {
        fprintf(stderr, "argument err");
        return -1;
    }
   
    FILE *out_file = fopen(argv[1], "w");
    if (out_file == NULL) {
        fprintf(stderr, "failed to open file");
        return -1;
    }
   
    char buffer[20];
    size_t ret;

    while ((ret = fread(buffer, 1, sizeof(buffer), stdin)) > 0) {
        // 检查缓冲区是否包含结束标记
        char *mark_ptr = strstr(buffer, END_MARK);
        if (mark_ptr != NULL) {
            // 写入结束标记之前的有效内容
            size_t valid_len = mark_ptr - buffer;
            if (valid_len > 0) {
                fwrite(buffer, 1, valid_len, out_file);
            }
            break;
        }
        // 正常写入读取到的内容
        if (fwrite(buffer, 1, ret, out_file) != ret) {
            if (ferror(out_file)) {
                perror("write err:");
            } 
        }
    }
    
    fclose(out_file); // 必须关闭文件,确保缓冲区数据刷入磁盘
    return 0;
}

使用时,输入完内容后输入###END###即可终止循环。

2. 支持文件重定向/管道输入

如果输入来源是文件而非终端,直接通过重定向或管道传递输入,stdin会在文件末尾自动触发EOF,fread返回0后循环正常终止。示例命令:

# 从input.txt读取输入,写入output.txt
./your_program output.txt < input.txt

# 通过管道传递输入
cat input.txt | ./your_program output.txt

注意事项

  • 原代码遗漏关闭输出文件的操作,可能导致数据滞留在缓冲区未写入磁盘,务必添加fclose(out_file)。
  • 结束标记要选择不会出现在正常输入中的字符串,避免误触发终止。
  • 若处理二进制数据,不要用字符串匹配,可改用特定字节序列作为结束标记。

内容的提问来源于stack exchange,提问作者professional pro

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 20:54:15