8
#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 之后而不是随后的读取。为什么会这样?

4

5 回答 5

22

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).

于 2009-08-07T05:26:20.333 回答
2

fgets 的联机帮助页告诉我:

不建议将 stdio 库中对输入函数的调用与对与输入流相关的文件描述符的 read(2) 的低级调用混为一谈;结果将是未定义的,很可能不是您想要的。

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

于 2009-08-07T12:18:31.063 回答
1

您可以使用 std fflush() 函数刷新标准输出缓冲区,也可以在 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() 函数。

希望有帮助....

于 2012-10-08T13:33:48.240 回答
1

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

于 2009-08-07T05:11:04.093 回答
0

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

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

于 2009-08-07T19:01:35.770 回答