【问题标题】:Read from stdin write to stdout in C在 C 中从标准输入读取写入标准输出
【发布时间】:2012-04-25 02:59:01
【问题描述】:

我正在尝试编写一个猫克隆来练习 C,我有这个代码:

#include <stdio.h>
#define BLOCK_SIZE 512
int main(int argc, const char *argv[])
{
    if (argc == 1) { // copy stdin to stdout
        char buffer[BLOCK_SIZE];
        while(!feof(stdin)) {
            size_t bytes = fread(buffer, BLOCK_SIZE, sizeof(char),stdin);
            fwrite(buffer, bytes, sizeof(char),stdout);
        }
    }
    else printf("Not implemented.\n");
    return 0;
}

我尝试了echo "1..2..3.." | ./cat./cat &lt; garbage.txt,但在终端上看不到任何输出。我在这里做错了什么?

编辑: 根据cmets和answers,我最终这样做了:

void copy_stdin2stdout()
{
    char buffer[BLOCK_SIZE];
    for(;;) {
        size_t bytes = fread(buffer,  sizeof(char),BLOCK_SIZE,stdin);
        fwrite(buffer, sizeof(char), bytes, stdout);
        fflush(stdout);
        if (bytes < BLOCK_SIZE)
            if (feof(stdin))
                break;
    }

}

【问题讨论】:

  • 不要使用feof作为你的循环条件;直到 您尝试读取文件末尾之后它才会返回 true,因此您的循环可能会经常执行一次。请检查 fread 的结果,如果它小于 BLOCK_SIZE, 调用 feof 以检查文件结尾。并且您需要在fwrite 调用之后添加fflush(stdout);
  • 这里 fread() 几乎总是产生零字节,除非您输入的正是 512 个字符。
  • @JohnBode 我的编辑看起来如何?
  • 更好,尽管您可能想检查写入stdout之前返回的字节数。你可以颠倒测试的意义,比如if (bytes &gt; 0) fwrite(...) else break;;毕竟,如果你得到 0 个字节,你还不如命中了 EOF。

标签: c io stdout stdin stdio


【解决方案1】:

尝试在fwrite() 之后调用fflush(stdout)

【讨论】:

    【解决方案2】:

    我可以引用我的答案:https://*.com/a/296018/27800

    fread(buffer, sizeof(char), block_size, stdin);
    

    【讨论】:

      【解决方案3】:

      您的问题似乎是 fread 的返回值。我修改了您的代码以打印出值字节,并且每次都得到 0。 fread 的手册页清楚地表明 fread 的返回值不是字符数。如果遇到 EOF,则返回值可能为零(在本例中为 0)。这是因为您试图读取 1 个大小为 BLOCK_SIZE 而不是 BLOCK_SIZE 大小为 1 的东西。

      【讨论】:

      • fread() 的结果是读取的字节数,但参数 2 和 3 确实指定了行为:“1 个大小为 n 的块”,而不是“最多 n 个大小为 1 的块”。在 OPs 代码中,他想要一个大小为 512 的块。
      • 是的,我在发布我的答案时阅读了您的答案。我刚刚添加了一个编辑以使其更清楚。对于该语言的新手来说,您在另一篇文章中的回答可能有点难以解析。我也投票给你的答案:)
      【解决方案4】:

      忽略我对fflush的评论;这不是问题。

      fread 调用中交换块大小和元素大小的顺序。您想读取大小为 1 的 BLOCK_SIZE 元素(sizeof (char) 定义为 1);您正在尝试读取 1 个大小为 BLOCK_SIZE 的元素,因此除非您输入 至少 BLOCK_SIZE 个字符,否则fread 将返回 0。IOW,您的 fread 调用必须是

      size_t bytes = fread(buffer, 1, sizeof buffer, stdin);
      

      fwrite 调用进行类似的更改。

      【讨论】: