2016-11-04 162 views
5

我必須讓兩個方案其中一個名爲發生器,它打印一些文字每秒Ç標準輸出到標準輸入實時

int main(int argc, char** argv) { 

    for(int i = 0; i < 10 ; i++) { 
     printf("something\n"); 
     sleep(1); 
    } 

    return (EXIT_SUCCESS); 
} 

再有第二個程序中調用它的消費者,現在,這應該從一個非標準輸入讀取添加一些其他文字並重新打印它。 讓它看起來像這樣:

int main(int argc, char** argv) { 


    char line[BUFSIZ]; 

    while(scanf("%s",line) != -1){ 
     printf("you entered %s \n",line); 
    } 

    return (EXIT_SUCCESS); 
} 

當我編譯並嘗試運行只有一個發電機像./generator它的工作原理如我所料。每秒鐘都會打印到控制檯。 但是當我嘗試運行它們都像./generator | ./消費者 它沒有按照我的預期工作。我等了10秒,之後得到10行你輸入了一些東西 我想打印「你每秒輸入一些東西」。

你能解釋一下爲什麼這樣,或者甚至更好地告訴我如何達到預期的行爲?

回答

3

來自printf的輸出被緩衝,並且只在緩衝區滿時出來。你可以在消費者中調用setbuf()(一開始一次),使用NULL作爲第二個參數,將stdout上的緩衝區大小設置爲NULL。

#include <stdio.h> 
setbuf(stdout, NULL); 

這將導致輸出寫入標準輸出(即您的printf)立即出來。或者,您可以寫入stderr,默認情況下該緩衝區大小爲NULL。 (或者,作爲另一種選擇,每次你想將緩衝區內容清除到終端時,你都可以在標準輸出上調用fflush)。

+1

或者你也可以使用stdbuf -o0 ./generator關閉緩衝命令行| 。/ consumer –

+0

@RomanHocke等待有一個程序改變另一個進程預執行程序的用戶模式行爲?那麼這很有趣... –

2

輸出被緩衝,所以stdio庫一直等到它有一堆數據,通常是4千字節,然後立即輸出。

,每當你想輸出實際輸出的調用只需添加到fflush

fflush(stdout); 

它的工作方式不同,當輸出直接發送到終端。標準輸出隨後進行行緩衝,因此緩衝區在每個行尾字符後都被刷新。

4

C I/O被緩衝。當使用終端I/O時,緩衝紀律爲行緩衝,因此在發送\n時內容被刷新爲輸出。當您使用管道時,緩衝紀律是全緩衝,以便僅當緩衝區已滿(無論內容是什麼)時才刷新內容。

您可以:

  1. 每次你必須真正寫在數據時間flush(stdout)
  2. 改變任何寫操作之前,要setvbuf通話緩衝區紀律。
-3

你應該使用線程來執行你的程序並行的部分:

#include <iostream> 
#include <thread> 
#include <unistd.h> 

using namespace std; 
void Print() { 


sleep(1); 
cout << "Thread trolling you!!!\n"; 
Print(); 
} 

int main() { 
string g; 
thread ttt(Print); //create thread, from now Print() runs parallel to 
cin >> g;   //the rest of int main() 
cout << g; 
ttt.join();   //join threads 
return (0); 
} 
+0

只是一個例子不是你的問題的直接解決方案。 – Legolas

+1

遞歸函數沒有有限的最大深度?我不認爲C++保證了尾部呼叫優化,所以這有點不好。 – hyde

+0

此外這個答案似乎錯過了很不好的問題... – hyde

相關問題