2016-11-04 54 views
5

Tôi có thực hiện hai chương trình một trong số họ được đặt tên máy phát điện mà in một số văn bản mỗi giâyc stdout để stdin thời gian thực

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

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

    return (EXIT_SUCCESS); 
} 

sau đó một có một chương trình thứ hai gọi nó là người tiêu dùng bây giờ, mà phải đọc từ một đầu vào standart thêm vào nó một số văn bản khác và in lại nó. Hãy cho nó trông như thế này:

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


    char line[BUFSIZ]; 

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

    return (EXIT_SUCCESS); 
} 

khi tôi biên dịch chúng và cố gắng chỉ chạy một máy phát điện như ./generator nó hoạt động như tôi mong đợi. mỗi thứ hai một cái gì đó là in để điều khiển. nhưng khi tôi cố gắng chạy cả hai như ./generator | ./consumer nó không hoạt động như tôi mong đợi. Tôi chờ 10 giây và sau đó nhận được 10 dòng bạn đã nhập một cái gì đó tôi muốn in "bạn đã nhập thứ gì đó" mỗi giây.

Bạn có thể giải thích cho tôi lý do tại sao điều này là như vậy hay thậm chí tốt hơn là tel cho tôi cách đạt được hành vi mong đợi?

Trả lời

3

Đầu ra từ printf của bạn đang được đệm và chỉ xuất hiện khi bộ đệm đầy. Bạn có thể gọi setbuf() trong người tiêu dùng (một lần ở đầu) với NULL làm đối số thứ 2, để thiết lập kích thước bộ đệm trên stdout thành NULL.

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

Điều này sẽ gây ra kết quả được viết bằng phương pháp stdout (tức là printf) của bạn xuất hiện ngay lập tức. Hoặc bạn có thể viết thư cho stderr, theo mặc định có kích thước bộ đệm NULL. (Hoặc, như là một thay thế, bạn có thể gọi fflush trên stdout mỗi khi bạn muốn xóa các nội dung đệm ra đến thiết bị đầu cuối).

+1

Hoặc bạn có thể tắt đệm trên dòng lệnh sử dụng stdbuf -o0 ./generator | ./ consumer –

+0

@RomanHocke Chờ đợi có tồn tại một chương trình thay đổi hành vi chế độ người dùng cho một quá trình trước exec khác? Thật thú vị ... –

2

Đầu ra được đệm, do đó thư viện stdio đợi cho đến khi nó có một loạt dữ liệu, thường là 4 kilobyte và sau đó xuất ra cùng một lúc.

Chỉ cần thêm một cuộc gọi đến fflush bất cứ khi nào bạn muốn đầu ra để thực sự được đầu ra:

fflush(stdout); 

Nó hoạt động khác khi đầu ra sẽ được gửi trực tiếp đến các thiết bị đầu cuối. Đầu ra tiêu chuẩn sau đó được lưu vào bộ đệm dòng, do đó bộ đệm được xóa sau mỗi ký tự cuối dòng.

4

C I/O được đệm. Khi sử dụng thiết bị đầu cuối I/O, quy trình lưu vào bộ đệm là dòng đệm do đó nội dung được xả ra khi \n được gửi. Khi bạn sử dụng đường ống, chế độ đệm là toàn bộ đệm sao cho nội dung bị xóa khi bộ đệm đầy (bất kể nội dung là gì).

Bạn có thể:

  1. flush(stdout) mỗi khi bạn cần các dữ liệu được thực sự viết ra,
  2. thay đổi kỷ luật đệm bằng một cuộc gọi đến setvbuf trước khi bất kỳ ghi.
-3

Bạn nên sử dụng chủ đề để thực hiện các bộ phận của chương trình song song của bạn:

#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

chỉ là một ví dụ không phải là giải pháp trực tiếp cho vấn đề của bạn. – Legolas

+1

Chức năng đệ quy không giới hạn độ sâu tối đa? Tôi không nghĩ rằng C + + đã đảm bảo tối ưu hóa cuộc gọi đuôi, vì vậy đó là kinda ... xấu. – hyde

+0

Ngoài ra câu trả lời này dường như bỏ lỡ câu hỏi khá xấu ... – hyde

Các vấn đề liên quan