【问题标题】:write() to stdout and printf output not interleaved?write() 到 stdout 和 printf 输出没有交错?
【发布时间】:2009-08-07 05:05:06
【问题描述】:
#include <stdio.h>
#define MAXLEN 256

int main() {
  int n;
  char buf[MAXLEN];
  while((n = read(0,buf,sizeof(buf))) != 0){
    printf("n: %d:",n);
    write(1,buf,n);
  }
  return 1;
}

程序的输出(第一个read和第一个write由用户输入并由终端回显)是:

read
read
write
write
n: 5:n: 6:

printf 的输出是在标准输入中按 Ctrl+D 后出现的,而不是随后的读取。为什么会这样?

【问题讨论】:

    标签: c printf stdout


    【解决方案1】:

    Printf 被缓冲。

    您可以强制 printf 使用 fflush 调用“刷新”其缓冲区:

    #include <stdio.h>
    #define MAXLEN 256
    
    int main() {
      int n;
      char buf[MAXLEN];
      while((n = read(0,buf,sizeof(buf))) != 0){
        printf("n: %d:",n);
        fflush(stdout); /* force it to go out */
        write(1,buf,n);
      }
      return 1;
    }
    

    一般来说,printf() 被缓冲是一件好事。无缓冲输出,特别是对于需要屏幕更新等的可见控制台,速度很慢。足够慢,以至于经常打印的应用程序会被它直接拖慢(尤其是在 Windows 平台上;Linux 和 unix 通常受到的影响较小)。

    然而,printf() 被缓冲会咬你,如果你也 fprintf(stderr,) - stderr 被故意不缓冲。因此,您可能会收到一些 printf() 丢失的消息;如果您写入另一个也与终端关联的 FILE 句柄,并且可能没有缓冲,请确保您首先明确地 fflush(stdout)

    【讨论】:

    • 您也可以在执行任何 IO 之前使用 setvbuf() 更改缓冲模式。
    • printf()buffered”是什么意思?
    • @MattDiPasquale printf 写入标准输出,标准输出被缓冲(默认)。它只被冲洗,例如在换行符上。
    • 还应该提到换行符('\n')会导致标准输出被刷新
    • @carefulnow1:取决于它指向的位置。如果它要去一个文件,它通常是块缓冲的,只有当它去一个终端时,它通常是行缓冲的。
    【解决方案2】:

    fgets 的手册页告诉我:

    不建议混合调用来自 stdio 的输入函数 具有对文件描述符关联的 read(2) 的低级调用的库 与输入流一起吃;结果将是不确定的,非常 可能不是你想要的。

    所以最好的解决方案是不要在同一个描述符上使用 write 和 printf。

    【讨论】:

    【解决方案3】:

    Printf 正在使用 stdio 并已缓冲。 通过将更改发送到 "n: %d:\n" 来推出它

    【讨论】:

    • 要么这样,要么不混合输出通道——即使用同一个函数输出所有内容。
    • \n 不保证刷新它。
    • stdout 是行缓冲的,除非它定向到非交互式设备。
    【解决方案4】:

    您可以使用 std fflush() 函数来刷新 std out 缓冲区,也可以在 printf 内的控制字符串末尾使用附加的 \n。像这样的

    printf("\n :%d:\n",n);
    

    在 C 中使用 write() 和 read() 函数总是比 printf() 和 scanf() 更好。 Printf 和 scanf 有一些问题,例如 printf 将字符串参数存储在标准输出缓冲区中。因此需要通过 fflush 函数或通过 \n 完成手动刷新。在一个小型的 hello world 打印程序中,您不会发现 stdout 缓冲区在程序执行结束时被刷新这样的问题。更好地使用 write() 效果很好。 scanf 还存在读取空格的问题以及与 stdin 缓冲区相关的许多其他问题。

    例如在下面的代码中:

    main()  {   char a; int i=0,c; for(;i<2;i++) { scanf("%d",&c); scanf("%c",&a);} }
    

    上面的程序在按下回车键时遇到了将 \n 读入标准输入的问题。我们可以解决这个问题,但不能刷新标准输入缓冲区或使用 \n 字符。使用 read() 和 write() 函数总是更好。

    希望对您有所帮助....

    【讨论】:

      【解决方案5】:

      使用 fwrite(流版本)而不是 write。

      请注意,虽然与文件编号 1 相关联,但它不是一回事。

      【讨论】:

        猜你喜欢
        • 2018-06-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-01-31
        • 1970-01-01
        • 2014-07-18
        相关资源
        最近更新 更多