web-dev-qa-db-ja.com

stdoutへのwrite()とprintf出力がインターリーブされていませんか?

#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を押した後に表示されます。なぜこれが起こるのですか?

7
s_itbhu

Printfはバッファリングされます。

Fflush呼び出しを使用して、printfにバッファを「フラッシュ」させることができます。

_#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() --stderrも意図的にバッファリングされていない場合、バッファリングされているfprintf(stderr,)はあなたを噛みます。結果として、printf()が欠落しているメッセージが表示される場合があります。同じく端末に関連付けられている、バッファリングされていない可能性のある別のFILEハンドルに書き込む場合は、最初に明示的にfflush(stdout)を実行するようにしてください。

21
Will

Fgetsのマンページには次のように書かれています。

Stdioライブラリからの入力関数への呼び出しを、入力ストリームに関連付けられたファイル記述子のread(2)への低レベルの呼び出しと混合することはお勧めできません。結果は未定義であり、おそらくあなたが望むものではありません。

したがって、最善の解決策は、同じ記述子でwriteとprintfを使用しないことです。

2
Kasper

Std fflush()関数を使用してstd outバッファーをフラッシュするか、printf内の制御文字列の最後に追加の\ nを使用することができます。このようなもの

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

Printf()およびscanf()の代わりに、Cでwrite()およびread()関数を使用することをお勧めします。 printfとscanfには、printfが文字列パラメータをstdoutバッファに格納するなどの問題があります。したがって、手動フラッシュが必要です。これは、フラッシュ機能または\ nを使用して実行されます。小さなhelloworld印刷プ​​ログラムでは、プログラムの実行の最後にstdoutバッファがフラッシュされるなどの問題は発生しません。正常に動作するwrite()を使用することをお勧めします。 scanfには、スペースの読み取りの問題や、stdinバッファーに関連する他の多くの問題もあります。

たとえば、以下のコードでは次のようになります。

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

上記のプログラムは、Enterキーを押すと\ nをstdinに読み込む問題が発生しました。これは解決できましたが、stdinバッファをフラッシュしたり、\ n文字を使用したりすることはできませんでした。 read()関数とwrite()関数を使用することをお勧めします。

お役に立てば幸いです。

1
m4n1c

Printfはstdioを使用しており、バッファリングされています。 「n:%d:\ n」に変更を送信してプッシュします

1
Tim Williscroft

書き込みではなくfwrite(ストリームバージョン)を使用します。

ファイル番号1に関連付けられていますが、同じものではないことに注意してください。

0
njkayaker