将C程序通过管道自身串联后,输入Ctrl-D为何输出四次重复内容?
为什么
./e52 | ./e52会输出四次重复? 这问题挺有意思的,我来帮你一步步拆解清楚:
先明确你的程序逻辑
你的程序e52.c的核心逻辑很简单:
- 每次从输入读取一个字符
- 先输出这个字符一次
- 如果字符不是换行符,再输出一次
所以正常情况下,输入一个字符(比如1),会得到两次重复的输出(11),这和你用cat passwd.copy | ./e52时的表现完全一致。
两种管道场景的差异
场景1:cat passwd.copy | ./e52
这里cat把文件内容一次性输出到管道,作为e52的输入:
e52逐个读取文件里的每个字符,每个字符都输出两次- 当
cat读完文件后,会关闭管道的写端,e52读到EOF(-1),因为你的循环条件是ch > 0,-1不满足条件,循环直接退出,程序结束。最终结果就是文件里的每个字符都被重复一次,符合预期。
场景2:./e52 | ./e52
这是两个e52程序通过管道串联,第一个的输出作为第二个的输入,完整流程是这样的:
- 第一个
e52从终端标准输入读取内容,所以它会等待你输入字符(这就是你看到的“等待输入”) - 你输入
1然后按Ctrl-D(发送EOF信号):- 第一个
e52读取到1,输出两次变成11,然后读到EOF,循环退出,第一个程序结束并关闭管道写端 - 第二个
e52此时开始读取管道里的内容——也就是第一个程序输出的11 - 第二个
e52对这两个1分别处理:每个1都输出两次,所以第一个1变成11,第二个1也变成11,合起来就是1111,也就是四次重复
- 第一个
- 当第二个
e52读完管道里的所有内容,读到EOF,循环退出,程序结束。
额外的小建议
你的程序里有个潜在的问题:getchar()的返回值是int类型(因为它需要返回EOF这个特殊值,对应-1),但你把它赋值给了char ch。如果你的系统中char是无符号类型,那么-1会被转换成255,这时候ch > 0的条件会永远成立,导致程序进入死循环。
建议把代码改成更规范的写法:
/* Saved as e52.c */ #include <stdio.h> int main() { int ch; // 改成int类型,适配getchar的返回值 while ((ch = getchar()) != EOF) { // 用EOF判断结束,逻辑更可靠 putchar(ch); if (ch != '\n') putchar(ch); } return 0; }
内容的提问来源于stack exchange,提问作者faruk Karagoz
相关产品推荐
相关产品推荐

