2017-04-07 51 views
2

我有這個小程序:貓打破了計劃,手動標準輸入輸入不

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <sys/wait.h> 

int main() { 
    int orig = 1; 
    for (int i = 0; (i != 3) && orig; ++i) { 
     orig = orig && fork(); 
    } 
    if (orig) { 
     for (int i = 0; i != 3; ++i) { 
      wait(NULL); 
     } 
    } else { 
     int num; 
     scanf("%8d", &num); 
     printf("%d\n", num*num); 
    } 
} 

這應該簡單地廣場三個數字,它從stdin讀取。如果我在自己鍵入數字,它的工作原理:

akiiino$ ./out.out 
12345678 
12345678 
12345678 
260846532 
260846532 
260846532 

,但如果我用貓爲了同樣的目的,預期它不工作:

akiiino$ cat in.txt 
12345678 
12345678 
12345678 

akiiino$ cat in.txt | ./out.out 
260846532 
0 
0 

這背後有什麼奇怪的原因行爲,它是可以修復的嗎?我一直假設cat ing文件與輸入到stdin沒有什麼不同。

回答

3

不同之處在於,當您手動輸入3個號碼時,您正在讀取終端,低級讀取在換行符上終止。讓我們看看底下發生了什麼。

  1. 手動輸入:

    • 3個孩子已經開始並正在等待輸入
    • 你輸入一個號碼和一個新行
    • 底層read呼叫被換行,因爲終止你從終端讀取
    • 第一個孩子(得到讀的那個)有它的scanf調用解碼輸入和它的處理

    好吧,我們遍歷了2個其他孩子的

  2. 從一個文件或管道

    • 3個孩子開始閱讀相同的,都在等待輸入
    • 3數字和換行符立即可用
    • 第一個孩子的基礎read讀取並消耗stdio緩衝區中的所有輸入
    • 第一子(即得到所讀取的一個)具有其scanf呼叫解碼的(第一部分)的輸入的執行其處理

    但現在的2名其他兒童的是從位於一個文件/管道讀取文件結尾。他們的scanf返回0,但你無法控制它,他們讓初始未定義的值在num

您可以控制,這是不是在循環之前加入sleep(10),啓動程序由專人第一個孩子開始讀3號之前輸入的競爭狀態的問題。由於低電平讀取將以換行符終止(特殊tty情況),即使第一次讀取之前有3行可用,您仍然會得到第一種情況的相同輸出。

0

@Some程序員夥計已經說過,問題在於fork命令。 如果你嘗試./out.out < in.txt,它應該可以正常工作。

+0

其實不,它仍然不能正常工作。 – Akiiino

+0

奇怪的是,它對我來說很好(與貓+管道奇怪的配合,罰款與<)。那麼,你可能想要讓父進程讀取數據,並讓孩子進行微積分,無論如何你都要「分叉」。你也應該改變輸出的數據類型,'int'對於8位數字輸入肯定不夠好。 – RobinG