[英]cat breaks the program, manual stdin input doesn't
I have this small program: 我有这个小程序:
#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);
}
}
Which is supposed to simply square three numbers that it reads from stdin
. 它应该只是对从
stdin
读取的三个数字求平方。 And if I type the numbers in myself, it works: 如果我自己输入数字,它会起作用:
akiiino$ ./out.out
12345678
12345678
12345678
260846532
260846532
260846532
but if I use cat for the same purpose, it does not work as expected: 但是,如果我出于相同的目的使用cat,则无法正常工作:
akiiino$ cat in.txt
12345678
12345678
12345678
akiiino$ cat in.txt | ./out.out
260846532
0
0
What is the reason behind this weird behavior and is it fixable? 这种怪异行为背后的原因是什么,它是否可以解决? I've always assumed
cat
ing files was no different from typing them into stdin
. 我一直认为
cat
荷兰国际集团的文件,没有打字他们分为不同的stdin
。
The difference is that when you type the 3 numbers by hand , you are reading from a terminal and low level reads are terminated on newlines. 区别在于,当您手动键入3个数字时,您正在从终端读取数据,而低电平读取则在换行符处终止。 Let's look what happens under the hood.
让我们看看幕后情况。
manual input: 手动输入:
read
call is terminated by the newline because you read from a terminal read
调用由换行符终止,因为您是从终端读取的 scanf
call decode the input an does its processing scanf
调用,对输入进行解码并进行处理 Ok, we iterate the same for the 2 other childs 好吧,我们为其他两个孩子重复相同的操作
reading from a file or a pipe 从文件或管道读取
read
of first child reads and consumes all the input in the stdio buffer read
读取并消耗了stdio缓冲区中的所有输入 scanf
call decode the (first part of the) input an does its processing scanf
调用进行解码(输入的第一部分),并对其进行处理 But now the 2 other childs are reading from a file/pipe positioned at end of file. 但是现在其他两个孩子正在读取位于文件末尾的文件/管道。 Their scanf returns 0 but you fail to control it, and they let the initial undeterminated value in
num
. 他们的scanf返回0,但是您无法控制它,并且他们将未确定的初始值设为
num
。
You can control that it is not a problem of race condition by adding a sleep(10)
before the loop, starting the program an inputting by hand 3 numbers before first child begins to read. 您可以通过在循环之前添加
sleep(10)
,在第一个孩子开始阅读之前手动输入3个数字来启动程序来控制这不是竞赛条件的问题。 As the low level reads will be newline terminated (special tty case) you still get same output of the first case, even if the 3 lines are available before the first read. 由于低级读取将以换行符终止(特殊tty情况),即使在第一次读取之前有3行可用,您仍然会获得与第一种情况相同的输出。
Already said by @Some programmer dude, problem is with the fork
command. @Some程序员老兄已经说过,问题出在
fork
命令上。 If you try ./out.out < in.txt
, it should work fine. 如果尝试
./out.out < in.txt
,它应该可以正常工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.