2017-04-07 50 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